

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=&#34;auto&#34;>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/zoro.jpg">
  <link rel="icon" href="/img/zoro.jpg">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#efb9b9">
  <meta name="description" content="">
  <meta name="author" content="AgoniLay">
  <meta name="keywords" content="">
  
  <title>vue笔记 - AgoniLay的博客</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" />


  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" />
  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  
    
    
      
      <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@10.7.2/styles/arta.min.css" />
    
  

  
    <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
  



<!-- 主题依赖的图标库，不要自行修改 -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_ba1fz6golrf.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />

<!-- 自定义样式保持在最底部 -->

  
<link rel="stylesheet" href="/css/scroller.css">
<link rel="stylesheet" href="/css/bynode.css">
<link rel="stylesheet" href="/css/mouse.css">



  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    var CONFIG = {"hostname":"agonilay.github.io","root":"/","version":"1.8.11","typing":{"enable":true,"typeSpeed":150,"cursorChar":"❤","loop":false},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"copy_btn":true,"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading2.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null}},"search_path":"/local-search.xml"};
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
<meta name="generator" content="Hexo 5.4.0"></head>


<body>
  <header style="height: 70vh;">
    <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand"
       href="/">&nbsp;<strong>AgoniLay</strong>&nbsp;</a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item dropdown">
              <a class="nav-link dropdown-toggle" target="_self" role="button"
                 data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                <i class="iconfont icon-bookmark"></i>
                索引
              </a>
              <div class="dropdown-menu" aria-labelledby="navbarDropdown">
                
                  
                  
                  
                  <a class="dropdown-item" href="/archives/">
                    <i class="iconfont icon-archive-fill"></i>
                    归档
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/categories/">
                    <i class="iconfont icon-category-fill"></i>
                    分类
                  </a>
                
                  
                  
                  
                  <a class="dropdown-item" href="/tags/">
                    <i class="iconfont icon-tags-fill"></i>
                    标签
                  </a>
                
              </div>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                友链
              </a>
            </li>
          
        
          
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" data-toggle="modal" data-target="#modalSearch">&nbsp;<i
                class="iconfont icon-search"></i>&nbsp;</a>
          </li>
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

    <div class="banner" id="banner" parallax=true
         style="background: url('/img/zoro2.jpg') no-repeat center center;
           background-size: cover;">
      <div class="full-bg-img">
        <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
          <div class="page-header text-center fade-in-up">
            <span class="h3" id="subtitle" title="vue笔记">
              
            </span>

            
              <div class="mt-3">
  
    <span class="post-meta mr-2">
      <i class="iconfont icon-author" aria-hidden="true"></i>
      AgoniLay
    </span>
  
  
    <span class="post-meta">
      <i class="iconfont icon-date-fill" aria-hidden="true"></i>
      <time datetime="2021-08-14 15:14" pubdate>
        2021年8月14日 下午
      </time>
    </span>
  
</div>

<div class="mt-1">
  

  
    
    <span class="post-meta mr-2">
      <i class="iconfont icon-clock-fill"></i>
      
      
      385
       分钟
    </span>
  

  
  
    
      <!-- 不蒜子统计文章PV -->
      <span id="busuanzi_container_page_pv" style="display: none">
        <i class="iconfont icon-eye" aria-hidden="true"></i>
        <span id="busuanzi_value_page_pv"></span> 次
      </span>
    
  
</div>

            
			
			
          </div>

          
        </div>
      </div>
    </div>
  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="d-none d-lg-block col-lg-2"></div>
    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div class="py-5" id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">vue笔记</h1>
            
            <div class="markdown-body">
              <h1 id="Vue"><a href="#Vue" class="headerlink" title="Vue"></a>Vue</h1><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><h3 id="什么是-vue"><a href="#什么是-vue" class="headerlink" title="什么是 vue"></a>什么是 vue</h3><p>官方概念：Vue（读音 /vju:/，类似于 view），是一套用于构建用户界面的前端框架</p>
<ol>
<li>构建用户界面<ul>
<li>用 vue 往 html 页面中填充数据，非常的方便</li>
</ul>
</li>
<li>框架<ul>
<li>框架时一套现成的解决方案，程序员只能遵守框架的规范，去编写自己的业务功能</li>
<li>要学习 vue，就是在学习 vue 这个框架中规定的用法</li>
<li>vue 的指令、组件（是对 UI 结构的复用）、路由、Vuex、vue 组件库</li>
<li>只有把上面罗列的内容掌握以后，才有开发 vue 项目的能力</li>
</ul>
</li>
</ol>
<h3 id="vue-的特性"><a href="#vue-的特性" class="headerlink" title="vue 的特性"></a>vue 的特性</h3><p>vue 框架的特性，主要体现在两方面：</p>
<ol>
<li><p>数据驱动视图</p>
<ul>
<li>数据的变化<strong>会驱动视图</strong>自动更新</li>
<li>好处：当页面数据发生变化时，页面会自动重新渲染</li>
<li>数据驱动视图时单向的数据绑定</li>
</ul>
</li>
<li><p>双向数据绑定</p>
<blockquote>
<p>在网页中，form 表单负责<strong>采集数据</strong>，Ajax 负责<strong>提交数据</strong></p>
</blockquote>
<ul>
<li>在填写表单时，双向数据绑定额可以辅助开发者在不操作 DOM 的前提下，自动把用户填写的内容同步到数据源中</li>
<li>好处：开发者不需要手动操作 DOM 元素，来获取表单元素最新的值</li>
</ul>
</li>
</ol>
<blockquote>
<p>注意：数据驱动视图和双向数据绑定的底层原理是 MVVM（Model 数据源、View 视图、ViewModel 就是 vue 的实例）</p>
</blockquote>
<h4 id="MV-模式"><a href="#MV-模式" class="headerlink" title="MV* 模式"></a>MV* 模式</h4><h5 id="MVC"><a href="#MVC" class="headerlink" title="MVC"></a>MVC</h5><p>模型（Model）、视图（View）、控制器（Controller）</p>
<p>模型：代表应用程序的<strong>数据</strong>以及用于访问控制和修改这些数据的<strong>业务规则</strong>；</p>
<p>视图：用来组织模型的<strong>内容</strong>，发送用户的请求到控制器；</p>
<p>控制器：定义了应用程序的<strong>行为</strong>，将用户的请求映射到模型更新，选择视图作为请求的响应</p>
<h5 id="MVP"><a href="#MVP" class="headerlink" title="MVP"></a>MVP</h5><p>MVP（Model-View-Presenter）是由经典的 MVC 模式演变而来的，Presenter 负责逻辑的处理，Model 提供数据，View 负责显示</p>
<p>MVP 和 MVC 最大的区别在于：</p>
<ul>
<li>在 MVP 中 VIew 并不直接使用 Model，之间的通信通过 Presenter 进行的，所有的交互都在发生在 Presenter 内部</li>
<li>在 MVC 中 View 会直接从 Model 中读取数据而不是通过 Controller</li>
</ul>
<h5 id="MVVM"><a href="#MVVM" class="headerlink" title="MVVM"></a>MVVM</h5><p>MVVM（Model-View-ViewModel）是一种软件架构模式，是一种简化用户界面的事件驱动编程方式</p>
<p>核心是 <strong>数据驱动</strong> ，即 ViewModel，ViewModel 是 View 和 Model 的关系映射</p>
<ul>
<li>ViewModel 是一个值转换器（Value Converter），负责转换 Model 中的数据对象，使数据变得更加易于管理和使用</li>
<li>在 MVVM 中，View 和 Model 的中间 ViewModel 充当观察者的角色，两者不可直接通信</li>
</ul>
<p>核心的特性就是 <strong>数据双向绑定</strong> </p>
<h3 id="vue-的版本"><a href="#vue-的版本" class="headerlink" title="vue 的版本"></a>vue 的版本</h3><p>当前，vue 共有 3 个大版本，其中：</p>
<ul>
<li>2.x 版本的 vue 是目前企业级项目开发中的主流版本</li>
<li>3.x 版本的 vue 于 2020-09-19 发布，生态还不完善，尚未在企业级项目开发中普及和推广</li>
<li>1.x 版本的 vue 几乎被淘汰，不再建议学习与使用</li>
</ul>
<blockquote>
<p> vue 作者：尤雨溪，中国人</p>
</blockquote>
<h2 id="vue-的基本使用"><a href="#vue-的基本使用" class="headerlink" title="vue 的基本使用"></a>vue 的基本使用</h2><h3 id="基本使用步骤"><a href="#基本使用步骤" class="headerlink" title="基本使用步骤"></a>基本使用步骤</h3><ol>
<li>导入 vue.js 的 script 脚本文件</li>
<li>在页面中声明一个将要被 vue 控制的 DOM 区域</li>
<li>创建 vm 实例对象（vue 实例对象）</li>
</ol>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 希望 Vue 能够控制下面这个 div，帮我们在把数据填充到 div 内部 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><br>  &#123;&#123; username &#125;&#125;<br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br><span class="hljs-comment">&lt;!-- 1. 导入 Vue 的库文件，在 window 全局就有了 VUe 这个构造函数 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;./lib/vue-2.6.12.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 2. 创建 Vue 的实例对象 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-comment">// 创建 Vue 的实例对象</span></span><br><span class="javascript">  <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;</span><br><span class="javascript">    <span class="hljs-comment">// el 是固定的写法，表示 vm 实例要控制页面上的哪个区域，接收的值是一个选择器</span></span><br><span class="javascript">    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,</span><br><span class="javascript">    <span class="hljs-comment">// data 对象就是要渲染到页面上的数据</span></span><br><span class="javascript">    <span class="hljs-attr">data</span>: &#123;</span><br><span class="javascript">      <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;zhangsan&#x27;</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;)</span><br><span class="javascript">  </span><br><span class="javascript">  <span class="hljs-comment">// vm.$mount(&#x27;#app&#x27;) // 作用与 el 属性完全一样</span></span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>使用 vue-devtools 调试：在 chrome 中 F12 调试面板中的 vue 一项</p>
</blockquote>
<h2 id="vue-的指令和过滤器"><a href="#vue-的指令和过滤器" class="headerlink" title="vue 的指令和过滤器"></a>vue 的指令和过滤器</h2><h3 id="指令"><a href="#指令" class="headerlink" title="指令"></a>指令</h3><h4 id="概念和分类"><a href="#概念和分类" class="headerlink" title="概念和分类"></a>概念和分类</h4><p>指令（Directives）是 vue 为开发者提供的模板语法，用于辅助开发者渲染页面的基本结构。</p>
<p>vue 中的指令按照不同的用途可以分为如下 6 大类：</p>
<ul>
<li><p>内容渲染指令</p>
</li>
<li><p>属性绑定指令</p>
</li>
<li><p>事件绑定指令</p>
</li>
<li><p>双向绑定指令</p>
</li>
<li><p>条件渲染指令</p>
</li>
<li><p>列表渲染指令</p>
</li>
</ul>
<blockquote>
<p>注意：指令是 vue开发中最基础、最常用、最简单的知识点</p>
</blockquote>
<h4 id="内容渲染指令"><a href="#内容渲染指令" class="headerlink" title="内容渲染指令"></a>内容渲染指令</h4><p>内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下 3 个：</p>
<ul>
<li><code>v-text</code> </li>
<li><code>&#123;&#123; &#125;&#125;</code> </li>
<li><code>v-html</code> </li>
</ul>
<h5 id="v-text"><a href="#v-text" class="headerlink" title="v-text"></a>v-text</h5><p>更新元素的内容文本</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">&quot;username&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">v-text</span>=<span class="hljs-string">&quot;gender&quot;</span>&gt;</span>性别<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;</span><br><span class="javascript">    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,</span><br><span class="javascript">    <span class="hljs-attr">data</span>: &#123;</span><br><span class="javascript">      <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;zhangsan&#x27;</span>,</span><br><span class="javascript">      <span class="hljs-attr">gender</span>: <span class="hljs-string">&#x27;男&#x27;</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;)</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>注意缺点：v-text 指令会覆盖元素内默认的值</p>
</blockquote>
<h5 id="插值表达式语法"><a href="#插值表达式语法" class="headerlink" title="插值表达式语法 *"></a>插值表达式语法 *</h5><p>vue 提供的 <code>&#123;&#123; &#125;&#125;</code> 语法，专门用来解决 v-text 会覆盖默认文本内容的问题。这种 <code>&#123;&#123; &#125;&#125;</code> 语法的专业名称是<strong>插值表达式</strong>（英文名为：<strong>Mustache 语法</strong>）</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>姓名：&#123;&#123; username &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>性别：&#123;&#123; gender &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>在实际开发中用的最多，只是内容的占位符，不会覆盖原有的内容</p>
<blockquote>
<p>在 vue 提供的模板渲染语法中，除了支持绑定简单的数据值之外，还支持 Javascript 表达式的运算</p>
</blockquote>
<h5 id="v-html"><a href="#v-html" class="headerlink" title="v-html"></a>v-html</h5><p>v-text 指令和 插值表达式 只能渲染纯文本内容</p>
<p>v-html 可以把带有标签的字符串，渲染成真正的 HTML 内容</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-html</span>=<span class="hljs-string">&quot;info&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;</span><br><span class="javascript">    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,</span><br><span class="javascript">    <span class="hljs-attr">data</span>: &#123;</span><br><span class="javascript">      <span class="hljs-attr">info</span>: <span class="hljs-string">&#x27;&lt;h4 style=&quot;color: red; font-weight: bold;&quot;&gt;欢迎大家来学习 vue.js&lt;/h4&gt;&#x27;</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;)</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>动态渲染 HTML 是非常危险的，很容易导致 XSS 攻击，永远不要在用户提交的内容上使用 v-html</p>
</blockquote>
<h5 id="v-once"><a href="#v-once" class="headerlink" title="v-once"></a>v-once</h5><p>可以让元素或组件只渲染一次，不需要表达式。</p>
<p>之后再次渲染时，元素/组件及其所有的子节点将被视为静态内容并跳过，可以用于<strong>优化更新性能</strong>。</p>
<h5 id="v-pre"><a href="#v-pre" class="headerlink" title="v-pre"></a>v-pre</h5><p>用于跳过这个元素和它的子元素的编译过程，可以用来显示原始 Mustache 标签，不需要表达式。</p>
<p>对于大量没有指令的节点使用 v-pre 指令可以<strong>加快编译速度</strong>。</p>
<h5 id="v-cloak"><a href="#v-cloak" class="headerlink" title="v-cloak"></a>v-cloak</h5><p>这个指令保持在元素上知道关联实例编译结束，编译结束后该指令被移除，不需要表达式。</p>
<p>使用场景：</p>
<p>浏览器在加载页面时，如果网速较慢或者页面较大，那么浏览器在构造完 DOM 树后会在页面中直接显示 <code>&#123;&#123; value &#125;&#125;</code> 字样，直到 Vue 的 JS 文件加载完成，Vue 实例创建、模板编译后，才会被替换为数据对象中的内容。在这个过程中页面是有闪烁的，给用户的体验不好。</p>
<p>这时，CSS 规则 <code>[v-cloak] &#123; display: none &#125;</code> 配合 v-cloak 指令一起使用，就可以<strong>解决页面数据闪烁</strong>问题。</p>
<blockquote>
<p>在 Vue.js 独立版本的页面开发中，v-cloak 是非常有效的；但在较大的项目中均为模块化开发，不需要使用 v-cloak 指令</p>
</blockquote>
<h4 id="属性绑定指令"><a href="#属性绑定指令" class="headerlink" title="属性绑定指令"></a>属性绑定指令</h4><blockquote>
<p>注意：插值表达式只能用在元素的<strong>内容节点</strong>中，不能用在元素的<strong>属性节点</strong>中！</p>
</blockquote>
<h5 id="v-bind"><a href="#v-bind" class="headerlink" title="v-bind: | :"></a>v-bind: | :</h5><ul>
<li><p>在 vue 中，可以使用 <code>v-bind:</code> 指令,为元素的属性动态绑定属性值</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-bind:placeholder</span>=<span class="hljs-string">&quot;Tips&quot;</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>简写是英文的 <code>:</code> </p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">:placeholder</span>=<span class="hljs-string">&quot;Tips&quot;</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>动态属性名：</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">v-bind:</span>[<span class="hljs-attr">attrname</span>]=<span class="hljs-string">&quot;url&quot;</span>&gt;</span>链接<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>在使用 v-bind 属性绑定期间，如果绑定内容需要进行动态拼接，则字符串的外面应该包裹单引号，例如：</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">:title</span>=<span class="hljs-string">&quot;&#x27;box&#x27; + index&quot;</span>&gt;</span>这是一个 div<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>要避免没使用大写字符命名动态参数，浏览器会把元素的属性名全部强制值转换为小写字符</p>
</li>
</ul>
<h5 id="绑定-class"><a href="#绑定-class" class="headerlink" title="绑定 class"></a>绑定 class</h5><h6 id="对象语法"><a href="#对象语法" class="headerlink" title="对象语法"></a>对象语法</h6><figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;static&quot;</span></span><br><span class="hljs-tag">     <span class="hljs-attr">:class</span>=<span class="hljs-string">&quot;&#123; &#x27;active&#x27;: isActive, &#x27;text-danger&#x27;: hasError &#125;&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">data</span>: &#123;<br>    <span class="hljs-attr">isActive</span>: <span class="hljs-literal">true</span>,<br>    <span class="hljs-attr">hasError</span>: <span class="hljs-literal">false</span><br>  &#125;<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>最终渲染结果为：</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;static active&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>可以在数据属性中单独定义一个对象，然后绑定这个对象，或者考虑绑定一个返回对象的计算属性</p>
</blockquote>
<h6 id="数组语法"><a href="#数组语法" class="headerlink" title="数组语法"></a>数组语法</h6><figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">:class</span>=<span class="hljs-string">&quot;[isActive ? activeClass : &#x27;&#x27;, errorClass]&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">data</span>: &#123;<br>    <span class="hljs-attr">isActive</span>: <span class="hljs-literal">true</span>,<br>    <span class="hljs-attr">activeClass</span>: <span class="hljs-string">&#x27;active&#x27;</span>,<br>    <span class="hljs-attr">errorClass</span>: <span class="hljs-string">&#x27;text-danger&#x27;</span><br>  &#125;<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>最终渲染结果为：</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;active text-danger&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>可以在数组语法中使用对象语法来简化表达式</p>
</blockquote>
<h5 id="绑定-style"><a href="#绑定-style" class="headerlink" title="绑定 style"></a>绑定 style</h5><p>对象语法 和 数组语法 依然适用</p>
<ul>
<li><p>CSS 属性名可以用 <strong>驼峰式</strong>（camelCase）或 <strong>短横线分隔</strong>（’kebab-case’，记得用<strong>引号</strong>包起来）来命名</p>
</li>
<li><p>某些样式的不同浏览器内核前缀，在使用 :style 时 Vue.js 会<strong>自动侦测并添加相应的前缀</strong> </p>
</li>
<li><p>属性值可以包含多重值（一个数组），只会渲染数组中<strong>最后一个被浏览器支持的值</strong> </p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">:style</span>=<span class="hljs-string">&quot;&#123; display: [&#x27;-webkit-box&#x27;, &#x27;-ms-flexbox&#x27;, &#x27;flex&#x27;] &#125;&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
</ul>
<h4 id="事件绑定指令"><a href="#事件绑定指令" class="headerlink" title="事件绑定指令"></a>事件绑定指令</h4><h5 id="v-on"><a href="#v-on" class="headerlink" title="v-on: | @"></a>v-on: | @</h5><p>vue 提供了 v-on 事件绑定指令，用来辅助程序员为 DOM 元素绑定事件监听</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">v-on:click</span>=<span class="hljs-string">&quot;add&quot;</span>&gt;</span>+1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>通过 v-on 绑定的事件处理函数，需要在 <strong>methods</strong> 节点中进行声明，methods 与 data 节点同级</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">methods: &#123;<br>  add () &#123;<br>    <span class="hljs-built_in">this</span>.count++<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<ul>
<li><p>需要传参在方法名后面加括号即可</p>
</li>
<li><p>如果在方法中要修改或访问 data 中的数据，可以通过 this 访问到</p>
</li>
<li><p>简写是 <code>@</code> </p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;add&quot;</span>&gt;</span>+1<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
</ul>
<blockquote>
<p>注意：原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件，替换为 vue 的事件绑定形式后，分别为：v-on:click、v-on:input、v-on:keyup</p>
</blockquote>
<h5 id="event"><a href="#event" class="headerlink" title="$event"></a>$event</h5><p>vue 提供了内置变量 <strong>$event</strong>，用来表示原生 DOM 的事件参数对象 event</p>
<p>$event 可以解决事件参数对象 event 被覆盖的问题</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;app&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>count 的值是：&#123;&#123; count &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;add(1, $event)&quot;</span>&gt;</span>+N<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;</span><br><span class="javascript">    <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,</span><br><span class="javascript">    <span class="hljs-attr">data</span>: &#123;</span><br><span class="javascript">      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span></span><br><span class="javascript">    &#125;,</span><br><span class="javascript">    <span class="hljs-attr">methods</span>: &#123;</span><br><span class="javascript">      add (n, e) &#123;</span><br><span class="javascript">        <span class="hljs-built_in">this</span>.count += n</span><br><span class="javascript">        <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.count % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) &#123;</span><br><span class="javascript">          e.target.style.backgroundColor = <span class="hljs-string">&#x27;red&#x27;</span></span><br><span class="javascript">        &#125; <span class="hljs-keyword">else</span> &#123;</span><br><span class="javascript">          e.target.style.backgroundColor = <span class="hljs-string">&#x27;&#x27;</span></span><br><span class="javascript">        &#125;</span><br><span class="javascript">      &#125;</span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;)</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h5 id="修饰符"><a href="#修饰符" class="headerlink" title="修饰符"></a>修饰符</h5><h6 id="事件修饰符"><a href="#事件修饰符" class="headerlink" title="事件修饰符"></a>事件修饰符</h6><blockquote>
<p>在事件处理函数中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。</p>
</blockquote>
<p>vue 提供了事件修饰符的概念，来辅助程序员更方便的对事件的触发进行控制。</p>
<p>常用的 5 个事件修饰符如下：</p>
<ul>
<li><p><strong>.prevent</strong> ：阻止默认行为，调用 event.preventDefault()（例如：阻止 a 连接的跳转、阻止表单的提交等）</p>
</li>
<li><p><strong>.stop</strong> ：阻止事件冒泡，调用 event.stopPropagation()</p>
</li>
<li><p>.capture ：以捕获模式触发当前的事件处理函数</p>
<blockquote>
<p>捕获：由外至内，冒泡：由内至外</p>
</blockquote>
</li>
<li><p>.once ：绑定的事件只触发1次</p>
</li>
<li><p>.self ：只有在 event.target 是当前元素自身时触发事件处理函数</p>
</li>
<li><p><strong>.native</strong> ：监听组件根元素的原生事件</p>
</li>
<li><p>.passive ：以 { passive: true } 模式添加监听器</p>
</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;http://www.baidu.com&quot;</span> @<span class="hljs-attr">click.prevent</span>=<span class="hljs-string">&quot;show&quot;</span>&gt;</span>跳转到百度首页<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>修饰符可以串联一起使用，如：</p>
<ul>
<li>@click.prevent.self 会阻止所有的单击</li>
<li>@click.self.prevent 会阻止对元素自身的单击</li>
</ul>
</blockquote>
<h6 id="按键修饰符"><a href="#按键修饰符" class="headerlink" title="按键修饰符"></a>按键修饰符</h6><p>可以为键盘相关的事件添加按键修饰符，用的不多</p>
<ul>
<li><strong>.esc</strong>   <strong>.enter</strong>  .space  .tab  .delete（捕获删除键和退格键） </li>
<li>.up  .down  .left  .right    方向键</li>
<li>.ctrl  .alt  .shift  .meta（对应菜单键）</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> @<span class="hljs-attr">keyup.esc</span>=<span class="hljs-string">&quot;clearInput&quot;</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>注意，修饰键和常见按键并不相同，在和 keyup 事件一起使用时，事件触发时修饰键必须处于按下状态，可以使用 虚拟键代码(即按键对应的数字) 代替</p>
<h6 id="exact-修饰符"><a href="#exact-修饰符" class="headerlink" title=".exact 修饰符"></a>.exact 修饰符</h6><p>用于精确控制系统修饰符组合触发的事件</p>
<p>加上 .exact 后，当且仅当满足设置的修饰键时才会触发，如：</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 按下 ctrl 的同时即使按下其他键，也会触发事件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click.ctrl</span>=<span class="hljs-string">&quot;onClick&quot;</span>&gt;</span>A<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 只有在按住 ctrl 键而不按其他键时才会触发 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click.ctrl.exact</span>=<span class="hljs-string">&quot;onCtrlClick&quot;</span>&gt;</span>A<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 只有在没有按下系统键时才会触发 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click.exact</span>=<span class="hljs-string">&quot;onClick&quot;</span>&gt;</span>A<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h6 id="鼠标按钮修饰符"><a href="#鼠标按钮修饰符" class="headerlink" title="鼠标按钮修饰符"></a>鼠标按钮修饰符</h6><p>.left .middle .right  分别对应鼠标的左键、中键和右键</p>
<h4 id="双向绑定指令"><a href="#双向绑定指令" class="headerlink" title="双向绑定指令"></a>双向绑定指令</h4><h5 id="v-model"><a href="#v-model" class="headerlink" title="v-model"></a>v-model</h5><p>只有表单元素才可以使用 v-model 指令</p>
<blockquote>
<p>比如：input 输入框、textarea、select</p>
</blockquote>
<p>v-model 会忽略所有表单元素的 value、checked、selected 属性的初始值，而总是将 Vue 实例的数据属性作为数据来源</p>
<ul>
<li>复选框单独使用，v-model 绑定的值是一个布尔值，但多个复选框一起使用时绑定的是一个数组<ul>
<li>在使用单个复选框时，可以使用 true-value 和 false-value 属性来设置选中和未选中时 v-model 绑定的值</li>
</ul>
</li>
<li>单选按钮被选中时，v-model 绑定的数据属性的值会被设置为该单选按钮的 value 值</li>
<li>选择框的使用与复选框类似，单选时绑定的是选项的值（option 元素 value 属性的值），多选时绑定到一个数组</li>
</ul>
<blockquote>
<p>value-true、false-true、true 均可以使用 v-bind 指令绑定到数据属性上</p>
</blockquote>
<h5 id="专用修饰符"><a href="#专用修饰符" class="headerlink" title="专用修饰符"></a>专用修饰符</h5><ul>
<li><strong>.number</strong>：自动将用户的输入值转为数值类型</li>
<li><strong>.trim</strong>：自动过滤用户输入的首尾空白字符 </li>
<li><strong>.lazy</strong>：在 “change” 时而非 “input” 时更新</li>
</ul>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-model.number</span>=<span class="hljs-string">&quot;n1&quot;</span>&gt;</span> + <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">v-model.number</span>=<span class="hljs-string">&quot;n2&quot;</span>&gt;</span> = <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>&#123;&#123; n1 + n2 &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><br></code></pre></div></td></tr></table></figure>



<h4 id="条件渲染指令"><a href="#条件渲染指令" class="headerlink" title="条件渲染指令"></a>条件渲染指令</h4><blockquote>
<p>如果需要控制多个元素的显示或隐藏、创建或删除，可以用 template 元素来包裹这些元素，然后在 template 元素上使用指令</p>
</blockquote>
<h5 id="v-show"><a href="#v-show" class="headerlink" title="v-show"></a>v-show</h5><p>原理是：动态为元素添加或移除 <code>display: none</code> 样式，来实现元素的显示和隐藏</p>
<ul>
<li>如果要频繁的切换元素的显示状态，用 v-show 性能会更好</li>
</ul>
<h5 id="v-if"><a href="#v-if" class="headerlink" title="v-if"></a>v-if</h5><p>原理是：每次动态创建或移除元素，实现元素的显示和隐藏</p>
<ul>
<li>如果刚进入页面的时候，某些元素默认不需要显示，而且后期这个元素很可能也不需要被展示出来，此时 v-if 性能更好</li>
</ul>
<blockquote>
<p>在实际开发中，不用考虑性能问题，直接使用 v-if 即可</p>
</blockquote>
<p>v-if 可以单独使用，或配合 v-else 指令一起使用：</p>
<h5 id="v-else-v-else-if"><a href="#v-else-v-else-if" class="headerlink" title="v-else v-else-if"></a>v-else v-else-if</h5><p>这两个指令均必须配合 v-if 指令一起使用，否则将并不会被识别</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">&quot;type === &#x27;A&#x27;&quot;</span>&gt;</span>优秀<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-else-if</span>=<span class="hljs-string">&quot;type === &#x27;B&#x27;&quot;</span>&gt;</span>良好<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-else-if</span>=<span class="hljs-string">&quot;type === &#x27;C&#x27;&quot;</span>&gt;</span>一般<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-else</span>&gt;</span>差<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h5 id="key"><a href="#key" class="headerlink" title="key"></a>key</h5><p>Vue 会尽可能高效地渲染元素，通常会复用已有元素，而不是从头开始渲染，所以有以下情况：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vue">&lt;template v-if=&quot;loginType === &#x27;username&#x27;&quot;&gt;<br>	&lt;label&gt;用户名：&lt;/label&gt;<br>	&lt;input placeholder=&quot;请输入你的用户名&quot;&gt;<br>&lt;/template&gt;<br>&lt;template v-else&gt;<br>	&lt;label&gt;Email：&lt;/label&gt;<br>	&lt;input placeholder=&quot;请输入你的 Email&quot;&gt;<br>&lt;/template&gt;<br></code></pre></div></td></tr></table></figure>

<p>当从 用户名 切换到 Email 时，原先用户名中已输入的值还会保留，因为在切换时，vue 保留了 input 元素，仅仅替换了其 placeholder 属性值</p>
<p>解决：可以通过为元素添加一个具有唯一值的 <strong>key</strong> 属性</p>
<figure class="highlight plaintext"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vue">&lt;template v-if=&quot;loginType === &#x27;username&#x27;&quot;&gt;<br>	&lt;label&gt;用户名：&lt;/label&gt;<br>	&lt;input placeholder=&quot;请输入你的用户名&quot; key=&quot;username-input&quot;&gt;<br>&lt;/template&gt;<br>&lt;template v-else&gt;<br>	&lt;label&gt;Email：&lt;/label&gt;<br>	&lt;input placeholder=&quot;请输入你的 Email&quot; key=&quot;email-input&quot;&gt;<br>&lt;/template&gt;<br></code></pre></div></td></tr></table></figure>



<h4 id="列表渲染指令"><a href="#列表渲染指令" class="headerlink" title="列表渲染指令"></a>列表渲染指令</h4><blockquote>
<p>如果需要控制多个元素的循环，可以用 template 元素来包裹这些元素，然后在 template 元素上使用指令</p>
</blockquote>
<h5 id="v-for"><a href="#v-for" class="headerlink" title="v-for"></a>v-for</h5><p>v-for 指令需要使用 <strong>item in items</strong> 形式的特殊语法，其中：</p>
<ul>
<li>items 是待循环的数组</li>
<li>item 是被循环的每一项</li>
</ul>
<p>指令还支持一个可选的第二个参数，即当前项的<strong>索引</strong>，语法格式为 <strong>(item, index) in items</strong> </p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">table</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>索引<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Id<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>姓名<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">tr</span> <span class="hljs-attr">v-for</span>=<span class="hljs-string">&quot;(item, index) in list&quot;</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>&#123;&#123; index &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>&#123;&#123; item.id &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>&#123;&#123; item.name &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h6 id="v-for-遍历数组"><a href="#v-for-遍历数组" class="headerlink" title="v-for 遍历数组"></a>v-for 遍历数组</h6><blockquote>
<p>Vue 在检测到数组变化时，并不是直接重新渲染整个列表，而是最大化地复用 DOM 元素，替换的数组中，含有相同元素的项不会被重新渲染，无需担心性能问题。</p>
</blockquote>
<p>需要注意，以下方法引起的数组变动，Vue 不能检测到：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 通过索引直接设置数组项</span><br>vm.books[<span class="hljs-number">0</span>] = &#123;<span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;Java Web 开发详解&#x27;</span>&#125;<br><span class="hljs-comment">// 修改数组的长度</span><br>vm.books.length = <span class="hljs-number">1</span><br></code></pre></div></td></tr></table></figure>

<p>解决办法：</p>
<ul>
<li><p>使用 Vue 全局的 <strong>set()</strong> 方法</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.set(vm.books, <span class="hljs-number">0</span>, &#123;<span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;Java Web 开发详解&#x27;</span>&#125;)<br></code></pre></div></td></tr></table></figure></li>
<li><p>使用 Vue 实例的 <strong>$set()</strong> 方法</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">vm.$set(vm.books, <span class="hljs-number">0</span>, &#123;<span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;Java Web 开发详解&#x27;</span>&#125;)<br></code></pre></div></td></tr></table></figure></li>
<li><p>使用 数组的 <strong>splice()</strong> 方法</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">vm.books.splice(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, &#123;<span class="hljs-attr">title</span>: <span class="hljs-string">&#x27;Java Web 开发详解&#x27;</span>&#125;) <span class="hljs-comment">// 等同于通过索引修改数组</span><br>vm.books.splice(<span class="hljs-number">1</span>) <span class="hljs-comment">// 修改数组长度</span><br></code></pre></div></td></tr></table></figure></li>
</ul>
<h6 id="v-for-遍历对象"><a href="#v-for-遍历对象" class="headerlink" title="v-for 遍历对象"></a>v-for 遍历对象</h6><p>格式相同，为 <strong>value in object</strong>，可以按需添加参数 <strong>(value, key, index) in object</strong> </p>
<ul>
<li>value 代表属性值</li>
<li>key 表示属性名</li>
<li>index 表示索引</li>
</ul>
<p>同样需要注意，由于 JavaScript 的限制，Vue 不能检测对象属性的添加和删除</p>
<p>解决办法：</p>
<ul>
<li><p>使用 Vue 全局的 <strong>set()</strong> 和 <strong>delete()</strong> 方法 或 Vue 实例的 <strong>$set()</strong> 和 <strong>$delete()</strong> </p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.set(对象名, <span class="hljs-string">&#x27;属性名&#x27;</span>, <span class="hljs-string">&#x27;属性值&#x27;</span>)<br>vm.$set(对象名, <span class="hljs-string">&#x27;属性名&#x27;</span>, <span class="hljs-string">&#x27;属性值&#x27;</span>)<br>Vue.delete(对象名, <span class="hljs-string">&#x27;属性名&#x27;</span>)<br>vm.$delete(对象名, <span class="hljs-string">&#x27;属性名&#x27;</span>)<br></code></pre></div></td></tr></table></figure></li>
</ul>
<h6 id="v-for-遍历整数"><a href="#v-for-遍历整数" class="headerlink" title="v-for 遍历整数"></a>v-for 遍历整数</h6><p>v-for 指令也可以接受整数，会把模板重复对应次数</p>
<h5 id="key-1"><a href="#key-1" class="headerlink" title="key"></a>key</h5><p>官方建议：只要用到了 v-for 指令，那么一定要绑定一个 :key 属性，而且尽量把 id 作为 key 的值</p>
<p>key 值的要求：</p>
<ol>
<li><p><strong>字符串</strong>或<strong>数字</strong>类型</p>
</li>
<li><p>key 的值必须具有<strong>唯一性</strong>（即：key 的值不能重复，否则会报错）</p>
<blockquote>
<p>[Vue warn]: Duplicate keys detected: ‘ ‘.</p>
</blockquote>
</li>
<li><p>建议把数据项 <strong>id 属性</strong>的值作为 key 的值（因为 id 属性的值具有唯一性）</p>
</li>
<li><p><strong>使用 index 的值当作 key 的值没有任何意义</strong>（因为 index 的值不具有唯一性）</p>
<ul>
<li>当列表项发生变化时，索引可能会前向推进，单个不唯一</li>
</ul>
</li>
<li><p>建议使用 v-for 指令时一定要指定 key 的值（既提升性能、又防止列表状态紊乱）</p>
</li>
</ol>
<blockquote>
<p>不建议将 v-for 和 v-if 用在同一个元素上，可以用计算属性替代</p>
</blockquote>
<h3 id="filters-过滤器"><a href="#filters-过滤器" class="headerlink" title="filters 过滤器"></a>filters 过滤器</h3><blockquote>
<p>Vue3 中已经不可以使用内置过滤器(已删除)，Vue2 中仍可以</p>
</blockquote>
<p>过滤器（Filters）是 vue 为开发者提供的功能，常用于<strong>文本的格式化</strong>，或者数组数据的过滤与排序等。</p>
<p>过滤器可以用在两个地方：<strong>插值表达式</strong>和 <strong>v-bind 属性绑定</strong>；</p>
<p>过滤器应该被添加在 JavaScript 表达式的尾部，由 “管道符” <code>|</code> 进行调用</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 在插值表达式中调用 capitalize 过滤器，对 message 的值进行格式化 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>&#123;&#123; message | capitalize &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-comment">&lt;!-- 在 v-bind: 中调用 formatId 过滤器，对 rawId 的值进行格式化 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">v-bind:id</span>=<span class="hljs-string">&quot;rawId | formatId&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>注意点：</p>
<ul>
<li>在 filters 节点中定义私有过滤器，本质是一个函数</li>
<li>过滤器函数形参中的第一个参数，永远都是“管道符”前面的那个值，其他参数从第二个开始接收</li>
<li>过滤器中必须有一个 return 值</li>
<li>过滤器可以多个串联使用</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 过滤器函数，定义到 filters 节点之下，是私有过滤器</span><br><span class="hljs-attr">filters</span>: &#123;<br>  <span class="hljs-comment">// 注意：过滤器函数形参中的 val，永远都是“管道符”前面的那个值</span><br>  capitalize (val) &#123;<br>    <span class="hljs-comment">// 过滤器中必须有一个返回值</span><br>    <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&#x27;</span><br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="全局过滤器"><a href="#全局过滤器" class="headerlink" title="全局过滤器"></a>全局过滤器</h4><figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  Vue.filter(<span class="hljs-string">&#x27;capitalize&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">str</span>) =&gt;</span> &#123;</span><br><span class="javascript">    <span class="hljs-keyword">return</span> str.charAt(<span class="hljs-number">0</span>).toUpperCase() + str.slice(<span class="hljs-number">1</span>)</span><br><span class="javascript">  &#125;)</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>一般使用的都是全局过滤器</p>
<p>全局和私有过滤器名字一致，此时按照就近原则，调用的是私有过滤器</p>
<h2 id="directives-自定义指令"><a href="#directives-自定义指令" class="headerlink" title="directives 自定义指令"></a>directives 自定义指令</h2><p>vue 官方提供了 v-text、v-for、v-model、v-if 等常用的指令。除此之外 vue 还允许开发者自定义指令</p>
<ul>
<li><p>在使用自定义指令时，需要加上 <strong>v-</strong> 前缀</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">v-volor</span>&gt;</span>内容<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>在 template 结构中使用自定义指令时，可以通过等号 <strong>=</strong> 的方式，为当前指令动态绑定参数值</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">v-color</span>=<span class="hljs-string">&quot;color&quot;</span>&gt;</span>内容<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
</ul>
<h3 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h3><ul>
<li>私有自定义指令</li>
<li>全局自定义指令</li>
</ul>
<h3 id="私有自定义指令"><a href="#私有自定义指令" class="headerlink" title="私有自定义指令"></a>私有自定义指令</h3><p>在每个 vue 组件中，可以在 <strong>directives</strong> 节点下声明私有自定义指令</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">directives: &#123;<br>  <span class="hljs-attr">color</span>: &#123;<br>    bind (el) &#123;<br>      el.style.color = <span class="hljs-string">&#x27;pink&#x27;</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h3 id="全局自定义指令"><a href="#全局自定义指令" class="headerlink" title="全局自定义指令"></a>全局自定义指令</h3><p>全局共享的自定义指令通过 <strong>Vue.directive()</strong> 进行声明</p>
<p>接受两个参数，第一个为 指令的ID（即名字），第二个是一个定义对象或者函数对象，指令要实现的功能在这个对象中定义</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.directive(<span class="hljs-string">&#x27;name&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;&#125;)<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>一般使用自定义指令，都会定义在 全局上</p>
</blockquote>
<h3 id="钩子函数"><a href="#钩子函数" class="headerlink" title="钩子函数"></a>钩子函数</h3><h4 id="种类"><a href="#种类" class="headerlink" title="种类"></a>种类</h4><ul>
<li><strong>bind</strong>：只调用一次，当指令第一次绑定到元素时调用，当 DOM 更新时 bind 函数不会被触发。 </li>
<li>inserted：被绑定元素插入父节点时调用</li>
<li><strong>update</strong>：所在的组件的 VNode 更新时调用（无论指令的值是否发生了变化），但可能发生在子 VNode 更新之前</li>
<li>componentUpdated：指令所在组件的 VNode 及其子 VNode 全部更新后调用</li>
<li>unbind：只调用一次，指令与元素解绑时调用</li>
</ul>
<h4 id="参数"><a href="#参数" class="headerlink" title="参数"></a>参数</h4><ol>
<li><strong>el</strong> ：指令所绑定的元素，可以用来直接操作 DOM</li>
<li><strong>binding</strong> ：一个对象，包含以下属性：<ul>
<li>name：指令名，不包含 v- 前缀</li>
<li><strong>value</strong>：指令的绑定值，如果是表达式则 value 的值是最后的结果</li>
<li>oldValue：指令绑定的前一个值，仅在 update 和 componentUpdated 钩子函数中可用</li>
<li>expression：字符串形式的指令表达式，与 value 不同</li>
<li>arg：传给指令的参数，可选</li>
<li>modifiers：一个包含修饰符的对象</li>
</ul>
</li>
<li>vnode ：Vue 编译生成的虚拟节点</li>
<li>oldVnode ：上一个虚拟节点，仅在 update 和 componentUpdated 钩子函数中可用</li>
</ol>
<blockquote>
<p>除 el 参数以外，其他参数都是只读的，不可进行修改</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">directives: &#123;<br>  <span class="hljs-attr">color</span>: &#123;<br>    bind (el, binding) &#123;<br>      el.style.color = binding.value<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>注意：第二个参数中的 expression 值代表用户在 自定义指令后面输入的内容或表达式，而 value 才是可以获取到使用的值</p>
</blockquote>
<h4 id="简写"><a href="#简写" class="headerlink" title="简写"></a>简写</h4><p>如果 bind 和 update 函数中的逻辑完全相同，且只需要用到这两个钩子函数，则对象格式的自定义指令可以简写成函数格式：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">directives: &#123;<br>  color (el, binding) &#123;<br>    el.style.color = binding.value<br>  &#125;<br>&#125;<br>Vue.directive(<span class="hljs-string">&#x27;font-weight&#x27;</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">el, binding</span>) </span>&#123;<br>  el.style.fontWeight = binding.value<br>&#125;)<br></code></pre></div></td></tr></table></figure>



<h2 id="watch-监听器"><a href="#watch-监听器" class="headerlink" title="watch 监听器"></a>watch 监听器</h2><p>在 Vue 实例的选项对象的 <strong>watch</strong> 选项中定义</p>
<p>当需要在数据变化时执行异步或开销较大的操作时，使用监听器是最合适的</p>
<h3 id="方法格式的监听器"><a href="#方法格式的监听器" class="headerlink" title="方法格式的监听器"></a>方法格式的监听器</h3><p>缺点：</p>
<ol>
<li>无法在刚进到页面的时候自动触发</li>
<li>如果侦听的是一个对象，如果对象中的属性发生了变化，不会触发监听器</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">el</span>: <span class="hljs-string">&#x27;#app&#x27;</span>,<br>  <span class="hljs-attr">data</span>: &#123; <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;&#x27;</span> &#125;,<br> 	<span class="hljs-comment">// 所有的侦听器都应该被定义到 watch 节点下</span><br>  <span class="hljs-attr">watch</span>: &#123;<br>    <span class="hljs-comment">// 侦听器本质上是一个函数，要监视哪个数据的变化，就把数据名作为方法名即可</span><br>    <span class="hljs-function"><span class="hljs-title">username</span>(<span class="hljs-params">newVal, oldVal</span>)</span> &#123;<br>      <span class="hljs-comment">// ...</span><br>    &#125;<br>  &#125;<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>如果要侦听的是对象的子属性：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">watch: &#123;<br>  <span class="hljs-comment">// 如果要侦听的是对象的子属性，则必须包裹一层单引号</span><br>  <span class="hljs-string">&#x27;info.username&#x27;</span> (newVal) &#123;<br>    <span class="hljs-built_in">console</span>.log(newVal)<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>优先考虑使用方法格式的，如若满足不了需求再改用对象格式的</p>
</blockquote>
<h3 id="对象格式的监听器"><a href="#对象格式的监听器" class="headerlink" title="对象格式的监听器"></a>对象格式的监听器</h3><p>好处：</p>
<ol>
<li>可以通过 <strong>immediate</strong> 选项控制自动触发一次</li>
<li>可以通过 <strong>deep</strong> 选项控制开启深度侦听，可以侦听到对象中子属性的变化</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">data</span>: &#123;<br>    <span class="hljs-attr">info</span>: &#123;<br>      <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;admin&#x27;</span><br>    &#125;<br>  &#125;,<br>  <span class="hljs-attr">watch</span>: &#123;<br>    <span class="hljs-comment">// 定义对象格式的侦听器</span><br>    <span class="hljs-attr">info</span>: &#123;<br>      handler (newVal, oldVal) &#123;<br>        <span class="hljs-comment">// ...</span><br>      &#125;,<br>      <span class="hljs-comment">// immediate 选项的默认值是 false</span><br>      <span class="hljs-comment">// 作用是：控制侦听器是否自动触发一次</span><br>      <span class="hljs-attr">immediate</span>: <span class="hljs-literal">true</span>,<br>      <span class="hljs-comment">// deep 作用是：开启深度侦听</span><br>      <span class="hljs-attr">deep</span>: <span class="hljs-literal">true</span><br>    &#125;<br>  &#125;<br>&#125;)<br></code></pre></div></td></tr></table></figure>



<h2 id="computed-计算属性"><a href="#computed-计算属性" class="headerlink" title="computed 计算属性"></a>computed 计算属性</h2><p>表达式的逻辑过于复杂时，都应当考虑使用计算属性</p>
<p>计算属性指的是通过一系列运算之后，最终得到一个属性值，这个动态计算出来的属性值可以被 模板结构 或 methods 方法使用</p>
<h3 id="定义使用"><a href="#定义使用" class="headerlink" title="定义使用"></a>定义使用</h3><ul>
<li>要定义在 computed 节点之下，与 data 同级</li>
<li>计算属性在定义时要定义成“方法格式”</li>
<li>return 的值就是计算结果</li>
<li>使用时与使用 data 中属性值一样</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">var</span> vm = <span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">computed</span>: &#123;<br>    rgb () &#123; <span class="hljs-keyword">return</span> <span class="hljs-string">`rgb(<span class="hljs-subst">$&#123;<span class="hljs-built_in">this</span>.r&#125;</span>, <span class="hljs-subst">$&#123;<span class="hljs-built_in">this</span>.g&#125;</span>, <span class="hljs-subst">$&#123;<span class="hljs-built_in">this</span>.b&#125;</span>)`</span> &#125;<br>  &#125;<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<h3 id="计算属性缓存"><a href="#计算属性缓存" class="headerlink" title="计算属性缓存"></a>计算属性缓存</h3><p>计算属性是基于它的响应式依赖进行缓存的，只有在计算属性的相关响应式依赖发生改变时才会重新求值</p>
<h3 id="v-if-和-v-for-一起使用的替代方案"><a href="#v-if-和-v-for-一起使用的替代方案" class="headerlink" title="v-if 和 v-for 一起使用的替代方案"></a>v-if 和 v-for 一起使用的替代方案</h3><p>采用计算属性过滤后再遍历，好处：</p>
<ul>
<li>过滤后只会在要循环的数据发生变化时才被重新计算，过滤更高效</li>
<li>渲染只会遍历符合计算属性中条件的，渲染更高效</li>
<li>解耦渲染层的逻辑，可维护性（<strong>对逻辑的更改和扩展</strong>）更强</li>
</ul>
<h2 id="axios"><a href="#axios" class="headerlink" title="axios"></a>axios</h2><blockquote>
<p>axios 是一个专注于网络请求的库！</p>
</blockquote>
<p>axios（发音：艾克C奥斯）是前端圈最火的库。</p>
<h3 id="基本使用"><a href="#基本使用" class="headerlink" title="基本使用"></a>基本使用</h3><ol>
<li>调用 axios 之后，使用 async / await 进行简化</li>
<li>使用解构赋值，从 axios 封装的大对象中，把 data 属性解构出来</li>
<li>把解构出来的 data 属性，使用 : 进行重命名，一般都重命名为 <code>&#123; data: res&#125;</code> </li>
</ol>
<p>调用 axios 方法的返回值是一个 Promise 对象：</p>
<blockquote>
<p>axios 在请求到接口数据之后，在真正的数据之外，套了一层壳</p>
</blockquote>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123;<br>  config: &#123;&#125;,<br>  data: &#123;&#x27;真正的接口数据&#x27;&#125;,<br>  headers: &#123;&#125;,<br>  request: &#123;&#125;,<br>  status: xxx,<br>  statusText: &#x27;&#x27;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="发起-GET-请求"><a href="#发起-GET-请求" class="headerlink" title="发起 GET 请求"></a>发起 GET 请求</h4><figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">axios(&#123;<br>  <span class="hljs-comment">// 请求方式</span><br>  <span class="hljs-attr">method</span>: <span class="hljs-string">&#x27;GET&#x27;</span>,<br>  <span class="hljs-comment">// 请求的地址</span><br>  <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;&#x27;</span>,<br>  <span class="hljs-comment">// URL 中的查询参数</span><br>  <span class="hljs-attr">params</span>: &#123;<br>    <span class="hljs-attr">id</span>: <span class="hljs-number">1</span><br>  &#125;<br>&#125;).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> &#123;<br>  <span class="hljs-built_in">console</span>.log(res)<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>也可以使用 <strong>axios.get</strong> 方法：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">axios.get(<span class="hljs-string">&#x27;url地址&#x27;</span>, &#123;<br>  <span class="hljs-comment">// GET参数</span><br>  <span class="hljs-attr">params</span>: &#123;&#125; <br>&#125;)<br></code></pre></div></td></tr></table></figure>

<h4 id="发起-POST-请求"><a href="#发起-POST-请求" class="headerlink" title="发起 POST 请求"></a>发起 POST 请求</h4><figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">axios(&#123;<br>  <span class="hljs-attr">method</span>: <span class="hljs-string">&#x27;POST&#x27;</span>,<br>  <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;&#x27;</span>,<br>  <span class="hljs-comment">// 请求体</span><br>  <span class="hljs-attr">data</span>: &#123;<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;agoni&#x27;</span><br>  &#125;<br>&#125;).then(<span class="hljs-function">(<span class="hljs-params">res</span>) =&gt;</span> &#123;<br>  <span class="hljs-built_in">console</span>.log(res)<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>也可以使用 <strong>axios.post</strong> 方法：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">axios.post(<span class="hljs-string">&#x27;url&#x27;</span>, &#123; <span class="hljs-comment">/* POST请求体数据 */</span> &#125;)<br></code></pre></div></td></tr></table></figure>

<h4 id="await-和-async"><a href="#await-和-async" class="headerlink" title="await 和 async"></a>await 和 async</h4><ul>
<li>如果调用某个方法的返回值是 Promise 实例，则前面可以添加 await</li>
<li>await 只能用在被 async 修饰的方法中</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;<br>  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> axios(&#123;<br>    <span class="hljs-attr">method</span>: <span class="hljs-string">&#x27;POST&#x27;</span>,<br>    <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;&#x27;</span>,<br>    <span class="hljs-attr">data</span>: &#123;<br>      <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;agoni&#x27;</span><br>    &#125;<br>  &#125;)<br>  <span class="hljs-built_in">console</span>.log(result)<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="解构赋值"><a href="#解构赋值" class="headerlink" title="解构赋值"></a>解构赋值</h4><blockquote>
<p>解构赋值的时候可以使用 : 进行重命名</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>&#123;<br>  <span class="hljs-keyword">const</span> &#123; <span class="hljs-attr">data</span>: res &#125; = <span class="hljs-keyword">await</span> axios(&#123;<br>    <span class="hljs-attr">method</span>: <span class="hljs-string">&#x27;GET&#x27;</span>,<br>    <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;&#x27;</span><br>  &#125;)<br>  <span class="hljs-built_in">console</span>.log(res.data)<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h3 id="使用优化"><a href="#使用优化" class="headerlink" title="使用优化"></a>使用优化</h3><h4 id="挂载在-Vue-原型"><a href="#挂载在-Vue-原型" class="headerlink" title="挂载在 Vue 原型"></a>挂载在 Vue 原型</h4><p>使用 axios 需要各页面导入 axios 才可使用，比较麻烦</p>
<p>可以将 axios 挂载在 Vue 的原型上：</p>
<ol>
<li><p>在 main.js 中导入 axios</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;axios</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>配置请求根路径</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">axios.defaults.baseURL = <span class="hljs-string">&#x27;请求根路径&#x27;</span><br></code></pre></div></td></tr></table></figure></li>
<li><p>把 axios 挂载到 Vue.prototype 原型上</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.prototype.$http = axios<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>一般命名为 $http，今后在每个 .vue 组件中要发起请求，直接调用 this.$http 接口即可</p>
</blockquote>
</li>
</ol>
<p>缺点：</p>
<ul>
<li>不利于 api 接口的复用，所以一般不使用，了解即可</li>
</ul>
<h4 id="增强复用"><a href="#增强复用" class="headerlink" title="增强复用 *"></a>增强复用 *</h4><p>util/request.js：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> axios <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;axios&#x27;</span><br><br><span class="hljs-keyword">const</span> request = axios.create(&#123;<br>  <span class="hljs-comment">// 指定请求的根路径</span><br>  <span class="hljs-attr">baseURL</span>: <span class="hljs-string">&#x27;https://www.escook.cn&#x27;</span><br>&#125;)<br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> request<br></code></pre></div></td></tr></table></figure>

<p>api/articleAPI.js：</p>
<blockquote>
<p>一般以 API 命名结尾</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 文章相关的 API 接口</span><br><span class="hljs-keyword">import</span> request <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/utils/request.js&#x27;</span><br><br><span class="hljs-comment">// 向外按需导出一个 API 函数</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getArticleListAPI = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_page, _limit</span>) </span>&#123;<br>	<span class="hljs-keyword">return</span> request.get(<span class="hljs-string">&#x27;/articles&#x27;</span>, &#123;<br>    <span class="hljs-attr">params</span>: &#123;<br>      _page,<br>      _limit<br>    &#125;<br>  &#125;)<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>Home.vue：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 按需导入 API 接口</span><br><span class="hljs-keyword">import</span> &#123; getArticleListAPI &#125; <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/api/articleAPI.js&#x27;</span><br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>      <span class="hljs-comment">// 页码值</span><br>      <span class="hljs-attr">page</span>: <span class="hljs-number">1</span>,<br>      <span class="hljs-comment">// 每页显示多少条数据</span><br>      <span class="hljs-attr">limit</span>: <span class="hljs-number">8</span>,<br>      <span class="hljs-comment">// 文章列表数组</span><br>      <span class="hljs-attr">articleList</span>: []<br>    &#125;<br>  &#125;,<br>  <span class="hljs-attr">methods</span>: &#123;<br>    <span class="hljs-comment">// 封装获取文章列表数据的方法</span><br>    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-title">initArticleLsit</span>(<span class="hljs-params"></span>)</span> &#123;<br>      <span class="hljs-keyword">const</span> &#123; <span class="hljs-attr">data</span>: res &#125; = <span class="hljs-keyword">await</span> getArticleLsitAPI(<span class="hljs-built_in">this</span>.page, <span class="hljs-built_in">this</span>.limit)<br>      <span class="hljs-built_in">this</span>.articleList = res<br>    &#125;<br>  &#125;,<br>  <span class="hljs-function"><span class="hljs-title">create</span>(<span class="hljs-params"></span>)</span> &#123;<br>    <span class="hljs-built_in">this</span>.initArticleLsit()<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>



<h2 id="单页面应用程序"><a href="#单页面应用程序" class="headerlink" title="单页面应用程序"></a>单页面应用程序</h2><p>单页面应用程序（Single Page Application）简称 SPA，指一个 Web 网站中只有唯一的一个 HTML 页面，所有的功能和交互都在这唯一的一个页面完成</p>
<p>优点：</p>
<ol>
<li>前后端分离</li>
<li>良好的用户体验</li>
<li>减轻服务器压力</li>
<li>共用一套后端程序代码</li>
</ol>
<p>缺点：</p>
<ol>
<li>初次加载消耗多</li>
<li>前进后退有一定问题</li>
<li>SEO 难度较高</li>
</ol>
<h2 id="Vue-CLI"><a href="#Vue-CLI" class="headerlink" title="Vue CLI"></a>Vue CLI</h2><p>vue-cli 是 Vue.js 开发的标准工具。简化了程序员基于 webpack 创建工程化的 Vue 项目的工程</p>
<h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><p>安装 3.x 版本的 Vue 脚手架：</p>
<figure class="highlight php"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs php">npm install -g @vue/cli<br></code></pre></div></td></tr></table></figure>

<p>检查安装</p>
<figure class="highlight php"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs php">vue -V <span class="hljs-comment">// 检查是否安装 及 版本号</span><br></code></pre></div></td></tr></table></figure>

<p>看到 显示 <code>@vue/cli 版本号</code> 即为安装成功</p>
<h3 id="创建-Vue-项目"><a href="#创建-Vue-项目" class="headerlink" title="创建 Vue 项目"></a>创建 Vue 项目</h3><ol>
<li><p>基于 <strong>交互式命令行</strong> 的方式，创建 新版 vue 项目</p>
<figure class="highlight php"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs php">vue create my-project<br></code></pre></div></td></tr></table></figure>

<p>一般选择最后一项创建自定义</p>
</li>
<li><p>基于 <strong>图形化界面</strong> 的方式，创建 新版 vue 项目</p>
<figure class="highlight php"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs php">vue ui<br></code></pre></div></td></tr></table></figure></li>
<li><p>基于 2.x 的旧模板 ，创建 旧版 vue 项目（了解）</p>
<figure class="highlight php"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs php">npm install -g @vue/cli-init<br>vue init webpack my-project<br></code></pre></div></td></tr></table></figure></li>
</ol>
<h3 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h3><h4 id="public-文件夹"><a href="#public-文件夹" class="headerlink" title="public 文件夹"></a>public 文件夹</h4><h5 id="index-html"><a href="#index-html" class="headerlink" title="index.html"></a>index.html</h5><p>index.html 为项目主页面</p>
<p>其中 一行注释，表示生成脚本文件的将自动注入这个位置</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- built files will be auto injected --&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>id 属性为 app 的 div 之后将会被替换掉</p>
<blockquote>
<p>不要改动 inde.html 中的内容</p>
</blockquote>
<h5 id="favicon-ico"><a href="#favicon-ico" class="headerlink" title="favicon.ico"></a>favicon.ico</h5><p>网页的图标</p>
<h4 id="src-文件夹"><a href="#src-文件夹" class="headerlink" title="src 文件夹"></a>src 文件夹</h4><figure class="highlight stylus"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs stylus">assets 文件夹：存放项目中用到的静态资源文件，例如：css 样式表、图片资源<br>components 文件夹：存放程序员封装的、可复用的组件<br><span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.js</span> 是项目的入口文件。整个项目的运行，要先执行 <span class="hljs-selector-tag">main</span><span class="hljs-selector-class">.js</span><br>App<span class="hljs-selector-class">.vue</span> 是项目的根组件<br></code></pre></div></td></tr></table></figure>

<h5 id="main-js"><a href="#main-js" class="headerlink" title="main.js"></a>main.js</h5><p>将 main.js 中 render 函数指定的结构替换掉 index.html 中指定的 el区域 <code>&lt;div id=&quot;app&quot;&gt;&lt;/div&gt;</code> </p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 导入 vue 这个包，得到 vue 构造函数</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-comment">// 导入 App.vue 根组件，将来要把 App.vue 中的模板结构，渲染到 HTML 页面中</span><br><span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./App.vue&#x27;</span><br><br><span class="hljs-comment">// false 是开发模式，true 是发布模式</span><br><span class="hljs-comment">// 默认为 true</span><br>Vue.config.productionTip = <span class="hljs-literal">false</span><br><br><span class="hljs-comment">// 创建 Vue 的 实例对象</span><br><span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-comment">// el: &#x27;#app&#x27;,  // 这个和 $mount 二选一使用即可</span><br>  <span class="hljs-comment">// 把 render 函数指定的组件，渲染到 HTML 页面中</span><br>  <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>&#125;).$mount(<span class="hljs-string">&#x27;#app&#x27;</span>)<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>Vue 实例的 $mount() 方法，作用和 el 属性完全一样！</p>
</blockquote>
<h5 id="components-amp-views"><a href="#components-amp-views" class="headerlink" title="components &amp; views"></a>components &amp; views</h5><p>两个文件夹都是放组件的，区别在于：</p>
<ul>
<li>components 文件夹用来放各页面复用的组件</li>
<li>views 文件夹用来放 <strong>使用路由切换</strong> 的组件</li>
</ul>
<h3 id="运行流程"><a href="#运行流程" class="headerlink" title="运行流程"></a>运行流程</h3><blockquote>
<p>在工程化的项目中，vue 要做的事情很单纯：通过 main.js 把 App.vue 渲染到 index.html 的指定区域中</p>
</blockquote>
<ol>
<li>App.vue 用来编写待渲染的模板结构</li>
<li>index.html 中需要预留一个 el 区域</li>
<li>main.js 把 App.vue 渲染到了 index.html 所预留的区域中</li>
</ol>
<h2 id="component-组件"><a href="#component-组件" class="headerlink" title="component 组件"></a>component 组件</h2><p>组件 – 对 UI 结构的复用</p>
<p>组件化开发 – 根据封装的思想，把页面上可重用的 UI 结构封装为组件，从而方便项目的开发和维护</p>
<h3 id="组成结构"><a href="#组成结构" class="headerlink" title="组成结构"></a>组成结构</h3><ul>
<li>template -&gt; 组件的模板结构</li>
<li>script       -&gt; 业务逻辑区域，组件的 JavaScript 行为</li>
<li>style         -&gt; 样式区域</li>
</ul>
<p>语法结构</p>
<figure class="highlight plaintext"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs vue">&lt;template&gt;<br>&lt;!-- 这里用来定义 Vue 组件的 模板内容 --&gt;<br>&lt;/template&gt;<br><br>&lt;script&gt;<br>  // 这里用来定义 Vue 组件的 业务逻辑<br>  // 默认导出，这是固定写法！<br>  export default &#123;<br>    data: () &#123; return &#123;&#125; &#125;, // 私有数据<br>   	method: &#123;&#125; // 处理函数<br>  	// ... 其他业务逻辑<br>  &#125;<br>&lt;/script&gt;<br><br>&lt;style lang=&quot;&quot;&gt;<br>  /* 这里用于定义Vue组件的样式 */<br>&lt;/style&gt;<br></code></pre></div></td></tr></table></figure>

<ul>
<li>.vue 组件中的 data 不能像之前一样，不能指向对象，<strong>组件中的对象必须是一个函数</strong> </li>
<li>在组件中，this 表示当前组件的实例对象</li>
<li>style 中 加 lang 属性可以使用指定语法编写样式，例： <code>&lt;style lang=&quot;less&quot;&gt;&lt;/style&gt;</code> </li>
</ul>
<h3 id="使用组件的步骤"><a href="#使用组件的步骤" class="headerlink" title="使用组件的步骤"></a>使用组件的步骤</h3><h4 id="1-import-导入"><a href="#1-import-导入" class="headerlink" title="1. import 导入"></a>1. import 导入</h4><figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> Left <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/Left.vue&#x27;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>在 vue 中 @ 默认指向 src 根目录</p>
</blockquote>
<blockquote>
<p>vscode 中 @ 路径提示插件：Path Intellisense</p>
<p>使用步骤：</p>
<ol>
<li><p>在插件中搜索 Path Intellisense 安装并启用</p>
</li>
<li><p>在 vscode 设置文件 settings.json 中添加设置：</p>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123;<br>  <span class="hljs-comment">// 导入文件时是否携带文件的扩展名</span><br>  <span class="hljs-attr">&quot;path-autocomplete.extensionOnImport&quot;</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-comment">// 配置 @ 的路径显示</span><br>  <span class="hljs-attr">&quot;path-autocomplete.pathMappings&quot;</span>: &#123;<br>    <span class="hljs-attr">&quot;@&quot;</span>: <span class="hljs-string">&quot;$&#123;folder&#125;/src&quot;</span><br>  &#125;,<br>&#125;<br></code></pre></div></td></tr></table></figure></li>
</ol>
<p>注意点：要在 vue 中使用此插件，则必须保证 vscode 中打开的就是这个项目</p>
</blockquote>
<h4 id="2-注册组件"><a href="#2-注册组件" class="headerlink" title="2. 注册组件"></a>2. 注册组件</h4><p>使用 <strong>components</strong> 节点注册的是 私有子组件，只有本界面能用</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">components</span>: &#123;<br>    Left<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h5 id="注册全局组件"><a href="#注册全局组件" class="headerlink" title="注册全局组件"></a>注册全局组件</h5><p>通过 <strong>Vue.component()</strong> 方法，注册全局组件</p>
<p>接受两个参数，第一个为组件的名字，第二个是一个函数对象（使用 Vue.extend() 方法创建的组件构造器），也可以是一个选项对象</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.component(<span class="hljs-string">&#x27;Left&#x27;</span>, Left)<br>Vue.component(<span class="hljs-string">&#x27;name&#x27;</span>, [definition])<br></code></pre></div></td></tr></table></figure>

<p>例子：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">Vue.component(<span class="hljs-string">&#x27;ButtonCounter&#x27;</span>, &#123;<br>	data () &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>      <span class="hljs-attr">count</span>: <span class="hljs-number">0</span><br>    &#125;<br>  &#125;,<br>  <span class="hljs-attr">template</span>: <span class="hljs-string">&#x27;&lt;button @click=&quot;count++&quot;&gt;You clicked me &#123;&#123; count &#125;&#125; times.&lt;/button&gt;&#x27;</span><br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p><strong>Vue.extend()</strong> 方法接受一个参数，包含组件选项的对象，也就是 Vue.component() 方法中要接受的第二个参数格式，会生成一个<strong>组件构造器</strong> </p>
<h4 id="3-以标签形式使用"><a href="#3-以标签形式使用" class="headerlink" title="3. 以标签形式使用"></a>3. 以标签形式使用</h4><figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">Left</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Left</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>vscode 自动闭合标签插件：Auto Close Tag，不需要配置。</p>
</blockquote>
<h3 id="prop-props"><a href="#prop-props" class="headerlink" title="prop - props"></a>prop - props</h3><p>props 是组件的自定义属性</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">zujian</span> <span class="hljs-attr">:init</span>=<span class="hljs-string">&quot;value&quot;</span> /&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-comment">// props 是&quot;自定义属性&quot;，允许使用者通过自定义属性，为当前组件指定初始值</span><br>  <span class="hljs-comment">// 自定义属性的名字，是封装者自定义的（只要名称合法即可）</span><br>  <span class="hljs-comment">// props 中的数据，可以直接在模板结构中被使用</span><br>  <span class="hljs-attr">props</span>: [<span class="hljs-string">&#x27;属性值1&#x27;</span>, <span class="hljs-string">&#x27;属性值2&#x27;</span>, ...]<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="只读性"><a href="#只读性" class="headerlink" title="只读性"></a>只读性</h4><p>props 是<strong>只读的</strong>，不能直接修改 props 的值，否则终端会报错！</p>
<p>要想修改 props 的值，可以</p>
<ol>
<li>把 props 的值转存到 data 中，因为 data 中的数据都是可读可写的</li>
<li>如果接受数据后需要转换后使用，可以使用计算属性解决</li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">props</span>: [<span class="hljs-string">&#x27;init&#x27;</span>],<br>  <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>      <span class="hljs-comment">// 把 props 中的 init 值，转存到 count 上</span><br>      <span class="hljs-attr">count</span>: <span class="hljs-built_in">this</span>.init<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="prop-验证"><a href="#prop-验证" class="headerlink" title="prop 验证"></a>prop 验证</h4><p>可以使用 type default required 属性添加验证，或者也可以自定义验证函数</p>
<h5 id="type-值类型"><a href="#type-值类型" class="headerlink" title="type 值类型"></a>type 值类型</h5><p>在声明自定义属性时，可以通过 <strong>type</strong> 来定义属性的值类型</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">props</span>: &#123;<br>    <span class="hljs-attr">init</span>: &#123;<br>      <span class="hljs-comment">// 表示 init 的值类型必须是 Number 数字</span><br>      <span class="hljs-attr">type</span>: <span class="hljs-built_in">Number</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>仅判断类型：</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">props</span>: &#123;<br>    <span class="hljs-attr">init</span>: <span class="hljs-built_in">Number</span>,<br>    <span class="hljs-comment">// 多种可能的类型</span><br>    <span class="hljs-attr">tel</span>: [<span class="hljs-built_in">String</span>, <span class="hljs-built_in">Number</span>]<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>注意：null 和 undefined 会通过任何类型验证</p>
</blockquote>
<p>验证的 type 可以是右侧的原生构造函数：String、Number、Boolean、Array、Object、Date、Function、Symbol</p>
<p>也可以是一个自定义的构造函数</p>
<h5 id="default-默认值"><a href="#default-默认值" class="headerlink" title="default 默认值"></a>default 默认值</h5><p>在声明自定义属性时，可以通过 <strong>default</strong> 来定义属性的默认值</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">props</span>: &#123;<br>    <span class="hljs-comment">// 自定义属性A: &#123; /* 配置选项 */ &#125;</span><br>    <span class="hljs-attr">init</span>: &#123;<br>      <span class="hljs-comment">// 如果外界使用 Count 组件的时候，没有传递 init 属性，则默认值生效</span><br>      <span class="hljs-attr">default</span>: <span class="hljs-number">0</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h5 id="required-必填项"><a href="#required-必填项" class="headerlink" title="required 必填项"></a>required 必填项</h5><p>在声明自定义属性时，可以通过 <strong>required</strong> 选项，将属性设置为必填项，强制用户必须传递属性的值</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">props</span>: &#123;<br>    <span class="hljs-attr">init</span>: &#123;<br>      <span class="hljs-comment">// 必填项校验</span><br>      <span class="hljs-attr">required</span>: <span class="hljs-literal">true</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="非-prop-属性"><a href="#非-prop-属性" class="headerlink" title="非 prop 属性"></a>非 prop 属性</h4><p>在组件中定义的非 prop 属性：</p>
<ul>
<li>class 和 type 会合并</li>
<li>其他属性都是从外部提供给组件的值会替换掉组件内部设置好的值</li>
</ul>
<blockquote>
<p>如果不希望组件的根元素继承外部设置的属性，可以在组件的选项中设置： inheritAttrs: false</p>
</blockquote>
<h3 id="组件之间的样式冲突问题"><a href="#组件之间的样式冲突问题" class="headerlink" title="组件之间的样式冲突问题"></a>组件之间的样式冲突问题</h3><p>默认情况下，写在 .vue 组件中的样式会<strong>全局生效</strong>，因此很容易造成多个组件之间的样式冲突问题</p>
<p>导致组件之间样式冲突的根本原因是：</p>
<ol>
<li>单页面应用程序中，所有组件的 DOM 结构，都是基于唯一的 index.html 页面进行呈现的</li>
<li>每个组件中的样式，都会影响整个 index.html 页面中的 DOM 元素</li>
</ol>
<h4 id="scoped-解决"><a href="#scoped-解决" class="headerlink" title="scoped 解决"></a>scoped 解决</h4><p>为了提高开发效率和开发体验，vue 为 style 节点提供了 <strong>scoped</strong> 属性，从而防止组件之间的样式冲突问题</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;less&quot;</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="css"></span><br><span class="css">  <span class="hljs-comment">/* 样式 */</span></span><br><span class="css"></span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>原理：</p>
<ol>
<li>每个组件中的元素有特定的唯一的 data-v-xxx 属性</li>
<li>每个组件中的样式后面均跟上 <strong>属性选择器</strong> <code>[]</code> 即可</li>
</ol>
<h4 id="deep-样式穿透"><a href="#deep-样式穿透" class="headerlink" title="/deep/ 样式穿透"></a>/deep/ 样式穿透</h4><p>如果给当前组件的 style 节点添加了 scoped 属性，则当前组件的样式对其子组件是不生效的</p>
<p>如果想让某些样式对子组件生效，可以使用 <strong>/deep/</strong> 深度选择器</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css"></span><br><span class="css">  /deep/ <span class="hljs-selector-class">.title</span> &#123;</span><br><span class="css">    <span class="hljs-attribute">color</span>: pink;</span><br><span class="css">  &#125;</span><br><span class="css"></span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>原理：</p>
<ul>
<li>不加 /deep/ 时，生成的选择器格式为 <code>.title[data-v-xxx]</code> </li>
<li>加上 /deep/ 时，生成的选择器格式为 <code>[data-v-xxx] .title</code>  </li>
</ul>
<blockquote>
<p>注：当使用第三方组件库时，如果有修改组件默认样式的需求，需要用到 /deep/</p>
</blockquote>
<h3 id="组件的生命周期"><a href="#组件的生命周期" class="headerlink" title="组件的生命周期"></a>组件的生命周期</h3><h4 id="生命周期-amp-生命周期函数"><a href="#生命周期-amp-生命周期函数" class="headerlink" title="生命周期 &amp; 生命周期函数"></a>生命周期 &amp; 生命周期函数</h4><p>生命周期（Life Cycle）是指一个组件从 创建 -&gt; 运行 -&gt; 销毁 的整个阶段，强调的是一个时间段</p>
<p>生命周期函数：是由 vue 框架提供的内置函数，会伴随着组件的生命周期，自动按次序执行</p>
<blockquote>
<p>注意：生命周期强调的是时间段，生命周期函数强调的是时间点</p>
</blockquote>
<h4 id="组件生命周期函数的分类"><a href="#组件生命周期函数的分类" class="headerlink" title="组件生命周期函数的分类"></a>组件生命周期函数的分类</h4><p>new Vue() -&gt;</p>
<p>组件创建阶段：beforeCreate -&gt; <strong>created</strong> -&gt; beforeMount -&gt; <strong>mounted</strong> -&gt;</p>
<p>组件运行阶段：beforeUpdate -&gt; <strong>updated</strong> -&gt;</p>
<p>组件销毁阶段：beforeDestory -&gt; destoryed</p>
<ul>
<li>created 生命周期函数非常常用，经常在其中调用方法请求服务器的数据</li>
<li>mounted：其中经常操作 DOM 元素，做大部分操作</li>
</ul>
<blockquote>
<p><a target="_blank" rel="noopener" href="https://cn.vuejs.org/images/lifecycle.png">https://cn.vuejs.org/images/lifecycle.png</a> 生命周期图示</p>
</blockquote>
<img src="/2021/08/14/vue%E7%AC%94%E8%AE%B0/lifesycle.png" srcset="/img/loading2.gif" lazyload class title="lifesycle">

<h3 id="组件间的数据共享"><a href="#组件间的数据共享" class="headerlink" title="组件间的数据共享"></a>组件间的数据共享</h3><h4 id="组件间的关系"><a href="#组件间的关系" class="headerlink" title="组件间的关系"></a>组件间的关系</h4><blockquote>
<p>组件在被分装好之后，彼此之间是相互独立的，不存在关系</p>
</blockquote>
<p>在使用组件时，根据彼此的嵌套关系，形成了 父子关系、兄弟关系</p>
<h4 id="父子组件间数据共享"><a href="#父子组件间数据共享" class="headerlink" title="父子组件间数据共享"></a>父子组件间数据共享</h4><h5 id="父向子共享数据"><a href="#父向子共享数据" class="headerlink" title="父向子共享数据"></a>父向子共享数据</h5><p>父组件向子组件共享数据需要使用<strong>自定义属性</strong> </p>
<ul>
<li>父组件中使用 v-bind: 传递数据</li>
<li>子组件中通过 props 接收数据</li>
</ul>
<h5 id="子向父共享数据"><a href="#子向父共享数据" class="headerlink" title="子向父共享数据"></a>子向父共享数据</h5><p>子组件向父组件共享数据使用<strong>自定义事件</strong> </p>
<p>子组件</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>	data () &#123;<br>    <span class="hljs-keyword">return</span> &#123; <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> &#125;<br>  &#125;,<br>  <span class="hljs-attr">methods</span>: &#123;<br>    add () &#123;<br>      <span class="hljs-built_in">this</span>.count ++<br>      <span class="hljs-comment">// 修改数据时，通过 $emit() 触发自定义事件</span><br>      <span class="hljs-built_in">this</span>.$emit(<span class="hljs-string">&#x27;numchange&#x27;</span>, <span class="hljs-built_in">this</span>.count)<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>父组件</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">Son</span> @<span class="hljs-attr">numchange</span>=<span class="hljs-string">&quot;getNewCount&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Son</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;</span><br><span class="javascript">  data () &#123;</span><br><span class="javascript">    <span class="hljs-keyword">return</span> &#123; <span class="hljs-attr">countFromSon</span>: <span class="hljs-number">0</span> &#125;</span><br><span class="javascript">  &#125;,</span><br><span class="javascript">  <span class="hljs-attr">methods</span>: &#123;</span><br><span class="javascript">    getNewCount (val) &#123;</span><br><span class="javascript">      <span class="hljs-built_in">this</span>.countFromSon = val</span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;</span><br><span class="javascript">&#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>@click 事件是由 this.$emit(‘click’, {…}) 触发的</p>
</blockquote>
<h4 id="兄弟组件间的数据共享"><a href="#兄弟组件间的数据共享" class="headerlink" title="兄弟组件间的数据共享"></a>兄弟组件间的数据共享</h4><p>在 vue2.x 中，兄弟组件之间数据共享的方案是 <strong>EventBus</strong> </p>
<p>使用步骤：</p>
<ol>
<li><p>创建 eventBus.js 模块，并向外共享一个 Vue 的实例对象</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><br><span class="hljs-comment">// 向外共享 Vue 的实例对象</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">new</span> Vue()<br></code></pre></div></td></tr></table></figure></li>
<li><p>在数据发送方，调用 <code>bus.$emit(&#39;事件名称&#39;, 要发送的数据)</code> 方法触发<strong>自定义事件</strong> </p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> bus <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./eventBus.js&#x27;</span><br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  data () &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>      <span class="hljs-attr">msg</span>: <span class="hljs-string">&#x27;hello vue.js&#x27;</span><br>    &#125;<br>  &#125;,<br>  <span class="hljs-attr">methods</span>: &#123;<br>    sendMsg () &#123;<br>      bus.$emit(<span class="hljs-string">&#x27;share&#x27;</span>, <span class="hljs-built_in">this</span>.msg)<br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure></li>
<li><p>在数据接收方，在 <strong>created</strong> 生命周期函数中调用 <code>bus.$on(&#39;事件名称&#39;, 事件处理函数)</code> 方法注册一个自定义事件</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> bus <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./eventBus.js&#x27;</span><br><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  data () &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>      <span class="hljs-attr">msgFromLeft</span>: <span class="hljs-string">&#x27;&#x27;</span><br>    &#125;<br>  &#125;,<br>  created () &#123;<br>    bus.$on(<span class="hljs-string">&#x27;share&#x27;</span>, <span class="hljs-function"><span class="hljs-params">val</span> =&gt;</span> &#123;<br>      <span class="hljs-built_in">this</span>.msgFromLeft = val<br>    &#125;)<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure></li>
</ol>
<h3 id="动态组件"><a href="#动态组件" class="headerlink" title="动态组件"></a>动态组件</h3><p>动态组件指的是动态切换组件的显示与隐藏</p>
<h4 id="动态组件渲染"><a href="#动态组件渲染" class="headerlink" title="动态组件渲染"></a>动态组件渲染</h4><p>vue 提供了一个内置的 <strong><component></component></strong> 组件标签，专门用来实现动态组件的渲染</p>
<ol>
<li>component 标签是 vue 内置的，作用：组件的占位符</li>
<li>is 属性的值，表示要渲染的组件的名字，可以动态绑定</li>
<li>is 属性的值，应该是组件在 components 节点下的注册名称</li>
</ol>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-comment">&lt;!-- 渲染 Left 组件和 Right 组件 --&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">component</span> <span class="hljs-attr">:is</span>=<span class="hljs-string">&quot;comName&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">component</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">import</span> Left <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/Left.vue&#x27;</span></span><br><span class="javascript">  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;</span><br><span class="javascript">    data () &#123;</span><br><span class="javascript">      <span class="hljs-keyword">return</span> &#123;</span><br><span class="javascript">        <span class="hljs-comment">// 表示要展示的组件的名字</span></span><br><span class="javascript">        <span class="hljs-attr">comName</span>: <span class="hljs-string">&#x27;Left&#x27;</span></span><br><span class="javascript">      &#125;</span><br><span class="javascript">    &#125;,</span><br><span class="javascript">    <span class="hljs-attr">components</span>: &#123;</span><br><span class="javascript">      Left</span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h4 id="keep-alive"><a href="#keep-alive" class="headerlink" title="keep-alive"></a>keep-alive</h4><p>默认情况下，切换动态组件时无法保持组件的状态。此时可以使用 vue 内置的 <strong><keep-alive></keep-alive></strong> 组件保持动态组 件的状态</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">keep-alive</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">component</span> <span class="hljs-attr">:is</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">component</span>&gt;</span><br>  <br>  <br>  <br>  <br><span class="hljs-tag">&lt;/<span class="hljs-name">keep-alive</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h5 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h5><ul>
<li>当组件被缓存时，会自动触发组件的 <strong>deactivated</strong> 生命周期函数</li>
<li>当组件被激活时，会自动触发组件的 <strong>activated</strong> 生命周期函数</li>
<li>只有当组件第一次被创建时，才会触发 <strong>created</strong> 生命周期函数</li>
</ul>
<h5 id="include-amp-exclude-属性"><a href="#include-amp-exclude-属性" class="headerlink" title="include &amp; exclude 属性"></a>include &amp; exclude 属性</h5><blockquote>
<p>默认 keep-alive 所包含的所有组件均会被缓存！</p>
</blockquote>
<p>include 用来指定：只有名称匹配的组件会被缓存。</p>
<p>多个组件名之间使用 <code>,</code> 分隔</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">keep-alive</span> <span class="hljs-attr">include</span>=<span class="hljs-string">&quot;Left, Right&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">component</span> <span class="hljs-attr">:is</span>=<span class="hljs-string">&quot;&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">component</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">keep-alive</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>另外还有作用相反的 exclude 属性：表示排除</p>
<p>注意：include 和 exclude 不可以同时使用</p>
<h4 id="组件的-name-属性-扩展"><a href="#组件的-name-属性-扩展" class="headerlink" title="组件的 name 属性(扩展)"></a>组件的 name 属性(扩展)</h4><p>当给组件定义了 name 属性之后，组件的名称就是 name 属性的值</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;MyLeft&#x27;</span><br>&#125;<br></code></pre></div></td></tr></table></figure>

<ul>
<li>则在 include 和 exclude 中使用 components 节点中注册的名称无效，需使用 name 属性值</li>
<li>在调试工具中看到的也会是 name 属性值</li>
<li>建议开发中给所有组件定义一个专属名称，即 name 属性值</li>
</ul>
<h2 id="ref-引用"><a href="#ref-引用" class="headerlink" title="ref 引用"></a>ref 引用</h2><p>ref 用来辅助开发者在不依赖于 jQuery 的情况下，获取 DOM 元素或组件的引用</p>
<blockquote>
<p><strong>ref 属性起名推荐使用 xxxRef 格式</strong> </p>
</blockquote>
<h3 id="使用-ref-引用-DOM-元素"><a href="#使用-ref-引用-DOM-元素" class="headerlink" title="使用 ref 引用 DOM 元素"></a>使用 ref 引用 DOM 元素</h3><p>每个 vue 的组件实例上，都包含一个 $refs 对象，里面存储着对应的 DOM 元素或组件的引用。默认情况下， 组件的 $refs 指向一个空对象</p>
<p>步骤：</p>
<ol>
<li>给需要获取的 DOM 元素设置 ref 属性，一个组件内 ref 不可以重复</li>
<li>通过 <code>this.$refs.对应ref值</code> 获取对应 DOM 元素</li>
</ol>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;myh3&quot;</span>&gt;</span>MyRef 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;getRef&quot;</span>&gt;</span>获取 $refs 引用<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-attr">method</span>: &#123;</span><br><span class="javascript">    getRef () &#123;</span><br><span class="javascript">      <span class="hljs-comment">// 通过 this.$refs 访问</span></span><br><span class="javascript">      <span class="hljs-built_in">this</span>.$refs.myh3.style.color = <span class="hljs-string">&#x27;red&#x27;</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h3 id="使用-ref-引用组件实例"><a href="#使用-ref-引用组件实例" class="headerlink" title="使用 ref 引用组件实例"></a>使用 ref 引用组件实例</h3><p>步骤：</p>
<ol>
<li>给相应组件设置 ref 属性</li>
<li>通过 <code>this.$refs.组件对应ref值</code> 获取引用组件的实例</li>
<li>即可调用组件中的数据及方法</li>
</ol>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">my-counter</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;counterRef&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">my-counter</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;getRef&quot;</span>&gt;</span>获取 $refs 引用<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-attr">method</span>: &#123;</span><br><span class="javascript">    getRef () &#123;</span><br><span class="javascript">      <span class="hljs-comment">// 通过 this.$refs.引用的名称 可以引用组件的实例</span></span><br><span class="javascript">      <span class="hljs-comment">// 引用到组件的实例之后，就可以调用组件上的 数据 和 methods 方法</span></span><br><span class="javascript">      <span class="hljs-built_in">this</span>.$refs.counterRef.add()</span><br><span class="javascript">      <span class="hljs-built_in">this</span>.$refs.counterRef.count = <span class="hljs-number">0</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h3 id="this-nextTick-cb-延迟执行"><a href="#this-nextTick-cb-延迟执行" class="headerlink" title="this.$nextTick(cb) 延迟执行"></a>this.$nextTick(cb) 延迟执行</h3><p>组件的 <strong>$nextTick(cb)</strong> 方法，会把 cb 回调推迟到<strong>下一个 DOM 更新周期之后</strong>执行</p>
<p>通俗的理解是：<strong>等组件的 DOM 更新完成之后，再执行 cb 回调函数</strong>。从而能保证 cb 回调函数可以操作到最新的 DOM 元素</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;text&quot;</span> <span class="hljs-attr">ref</span>=<span class="hljs-string">&quot;inputRef&quot;</span> <span class="hljs-attr">v-if</span>=<span class="hljs-string">&quot;!inputVisible&quot;</span> @<span class="hljs-attr">blur</span>=<span class="hljs-string">&quot;inputVisible = true&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">v-else</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">&quot;showInput&quot;</span>&gt;</span>展示 input<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;</span><br><span class="javascript">    <span class="hljs-keyword">return</span> &#123;</span><br><span class="javascript">      <span class="hljs-attr">inputVisible</span>: <span class="hljs-literal">true</span></span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;,</span><br><span class="javascript">    <span class="hljs-attr">method</span>: &#123;</span><br><span class="javascript">      showInput () &#123;</span><br><span class="javascript">        <span class="hljs-built_in">this</span>.inputVisible = <span class="hljs-literal">false</span></span><br><span class="javascript">        <span class="hljs-built_in">this</span>.$nextTick(<span class="hljs-function">() =&gt;</span> &#123;</span><br><span class="javascript">          <span class="hljs-built_in">this</span>.$refs.inputRef.focus()</span><br><span class="javascript">        &#125;)</span><br><span class="javascript">      &#125;</span><br><span class="javascript">    &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>



<h2 id="slot-插槽"><a href="#slot-插槽" class="headerlink" title="slot 插槽"></a>slot 插槽</h2><h3 id="什么是插槽"><a href="#什么是插槽" class="headerlink" title="什么是插槽"></a>什么是插槽</h3><p>插槽（Slot）是 vue 为组件的封装者提供的能力。允许开发者在封装组件时，把不确定的、希望由用户指定的部分定义为插槽</p>
<p>可以把插槽认为是组件封装期间，为用户预留的内容的占位符</p>
<h3 id="基础用法"><a href="#基础用法" class="headerlink" title="基础用法"></a>基础用法</h3><p>在封装组件时，可以通过 <strong><slot></slot></strong> 元素定义插槽，从而为用户预留内容占位符</p>
<p>Left.vue</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;left-container&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Left 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 声明一个插槽区域 --&gt;</span><br>    <span class="hljs-comment">&lt;!-- vue 官方规定：每一个 slot 插槽，都要有一个 name 名称 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;default&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>App.vue</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">Left</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>用户自定义的内容，会在 slot 区域展示<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">Left</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<ul>
<li><p>如果在封装组件时没有预留任何 slot 插槽，则用户提供的任何自定义内容都会被丢弃</p>
</li>
<li><p>封装组件时，可以为预留的 slot 插槽提供后备内容（默认内容）。如果组件的使用者没有为插槽提供任何内容，则后备内容会生效</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;default&quot;</span>&gt;</span><br>  后备内容<br><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span><br></code></pre></div></td></tr></table></figure></li>
</ul>
<h3 id="具名插槽"><a href="#具名插槽" class="headerlink" title="具名插槽"></a>具名插槽</h3><p>如果在封装组件时需要预留多个插槽节点，则需要为每个 slot 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”</p>
<blockquote>
<p>注意：没有指定 name 名称的插槽， 会有隐含的名称叫做 “default”</p>
</blockquote>
<p>在向具名插槽提供内容的时候，我们可以在一个 template 元素上使用 <strong>v-slot:</strong> 指令，并以 v-slot 的参数的形式提供其名称</p>
<ul>
<li>v-slot: 指令不能直接用用在元素身上，必须用在 template 标签上</li>
<li>template 这个标签，它是一个虚拟的标签，只起到包裹性质的作用，但是，不会被渲染为任何实质性的 HTML 元素</li>
<li>简写：把参数之前的所有内容 (v-slot:) 替换为字符 <code>#</code> </li>
</ul>
<h3 id="作用域插槽"><a href="#作用域插槽" class="headerlink" title="作用域插槽"></a>作用域插槽</h3><p>在封装组件的过程中，可以为预留的 slot 插槽绑定 props 数据，这种带有 props 数据的 slot 叫做“<strong>作用域插槽</strong>”</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;content&quot;</span> <span class="hljs-attr">msg</span>=<span class="hljs-string">&quot;hello AgoniLay&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p><strong>接收</strong>作用域插槽对外提供的数据:</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> #<span class="hljs-attr">content</span>=<span class="hljs-string">&quot;scope&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>&#123;&#123; scope.msg &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>作用域插槽对外提供的数据对象，可以使用<strong>解构赋值</strong>简化数据的接收过程</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> #<span class="hljs-attr">content</span>=<span class="hljs-string">&quot;&#123; msg &#125;&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>&#123;&#123; msg &#125;&#125;<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>



<h2 id="router-路由"><a href="#router-路由" class="headerlink" title="router 路由"></a>router 路由</h2><p>路由（router）就是对应关系</p>
<p>前端路由就是指：Hash 地址 与 组件 之间的对应关系</p>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123; path: &#x27;#/home&#x27;, component: Home &#125;,<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>Hash 地址也就是 锚链接，location.hash 获取地址栏 Hash 地址</p>
</blockquote>
<h3 id="工作方式"><a href="#工作方式" class="headerlink" title="工作方式"></a>工作方式</h3><ol>
<li>用户点击了页面上的路由链接</li>
<li>导致了 URL 地址栏中的 Hash 值发生了变化</li>
<li>前端路由监听了到 Hash 地址的变化</li>
<li>前端路由把当前 Hash 地址对应的组件渲染到浏览器中</li>
</ol>
<h3 id="实现简单的前端路由"><a href="#实现简单的前端路由" class="headerlink" title="实现简单的前端路由"></a>实现简单的前端路由</h3><p>步骤1：通过 component 标签，结合 comName 动态渲染组件</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">component</span> <span class="hljs-attr">:is</span>=<span class="hljs-string">&quot;comName&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">component</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/Home.vue&#x27;</span></span><br><span class="javascript">  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;</span><br><span class="javascript">    <span class="hljs-function"><span class="hljs-title">data</span>(<span class="hljs-params"></span>)</span> &#123;</span><br><span class="javascript">      <span class="hljs-keyword">return</span> &#123;</span><br><span class="javascript">        <span class="hljs-attr">comName</span>: <span class="hljs-string">&#x27;Home&#x27;</span></span><br><span class="javascript">      &#125;</span><br><span class="javascript">    &#125;,</span><br><span class="javascript">    <span class="hljs-attr">components</span>: &#123;</span><br><span class="javascript">      Home</span><br><span class="javascript">    &#125;</span><br><span class="javascript">  &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>步骤2：在 App.vue 组件中，为 <a> 链接添加对应的 hash 值</a></p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;#/home&quot;</span>&gt;</span>首页<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;#/movie&quot;</span>&gt;</span>电影<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">&quot;#/about&quot;</span>&gt;</span>关于<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>步骤3：在 created 生命周期函数中，通过 window.onhashchange 函数监听浏览器地址栏中 hash 地址的变化，通过 location.hash 获取到实时hash 地址，动态切换要展示的组件的名称</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-function"><span class="hljs-title">created</span>(<span class="hljs-params"></span>)</span> &#123;<br>  <span class="hljs-built_in">window</span>.onhashchange = <span class="hljs-function">() =&gt;</span> &#123;<br>    <span class="hljs-keyword">switch</span> (location.hash) &#123;<br>      <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;#/home&#x27;</span>:<br>        <span class="hljs-built_in">this</span>.comName = <span class="hljs-string">&#x27;home&#x27;</span><br>        <span class="hljs-keyword">break</span><br>      <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;#/movie&#x27;</span>:<br>        <span class="hljs-built_in">this</span>.comName = <span class="hljs-string">&#x27;movie&#x27;</span><br>        <span class="hljs-keyword">break</span><br>      <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;#/about&#x27;</span>:<br>        <span class="hljs-built_in">this</span>.comName = <span class="hljs-string">&#x27;about&#x27;</span><br>        <span class="hljs-keyword">break</span><br>      <span class="hljs-attr">default</span>:<br>        <span class="hljs-keyword">break</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>



<h3 id="vue-router"><a href="#vue-router" class="headerlink" title="vue-router"></a>vue-router</h3><p>vue-router 是 vue.js 官方给出的路由解决方案。它只能结合 vue 项目进行使用，能够轻松的管理 SPA 项目中组件的切换</p>
<blockquote>
<p>vue-router 的官方文档地址：<a target="_blank" rel="noopener" href="https://router.vuejs.org/zh/">https://router.vuejs.org/zh/</a></p>
</blockquote>
<h4 id="安装和配置"><a href="#安装和配置" class="headerlink" title="安装和配置"></a>安装和配置</h4><p>步骤1：安装 vue-router 包</p>
<blockquote>
<p>在 vue2 的项目中，安装 vue-router 的命令如下：</p>
<figure class="highlight powershell"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs powershell">npm i vue<span class="hljs-literal">-router</span>@<span class="hljs-number">3.5</span>.<span class="hljs-number">2</span> <span class="hljs-literal">-S</span><br></code></pre></div></td></tr></table></figure>
</blockquote>
<p>步骤2：创建路由模块</p>
<blockquote>
<p>在 src 源代码目录下，新建 router/index.js 路由模块，并初始化如下的代码</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 1. 导入 Vue 和 VueRouter 的包</span><br><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue&#x27;</span><br><span class="hljs-keyword">import</span> VueRouter <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;vue-router&#x27;</span><br><br><span class="hljs-comment">// 2. 调用 Vue.use() 函数，把 VueRouter 安装为 Vue 的插件</span><br><span class="hljs-comment">// vue.use() 的作用就是：安装插件</span><br>Vue.use(VueRouter)<br><br><span class="hljs-comment">// 3. 创建路由的实例对象</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter()<br><br><span class="hljs-comment">// 4. 向外共享路由的实例对象</span><br><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> router<br></code></pre></div></td></tr></table></figure>
</blockquote>
<p>步骤3：导入并挂载路由模块</p>
<blockquote>
<p>在 src/main.js 入口文件中配置</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">import</span> router <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./router&#x27;</span><br><br><span class="hljs-keyword">new</span> Vue(&#123;<br>  <span class="hljs-attr">render</span>: <span class="hljs-function"><span class="hljs-params">h</span> =&gt;</span> h(App),<br>  router<br>&#125;).$mount(<span class="hljs-string">&#x27;#app&#x27;</span>)<br></code></pre></div></td></tr></table></figure>
</blockquote>
<h4 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h4><p>在 src/App.vue 组件中，使用 vue-router 提供的 <strong>router-link</strong> 和 <strong>router-view</strong> 声明路由链接和占位符</p>
<blockquote>
<p>使用 router-link 代替普通的 a 链接，to 属性内写 hash 地址，不需要写 #</p>
</blockquote>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;app-container&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>App2 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- 1. 定义路由链接 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/home&quot;</span>&gt;</span>首页<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/movie&quot;</span>&gt;</span>电影<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/about&quot;</span>&gt;</span>关于<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br><br>    <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span><br><br>    <span class="hljs-comment">&lt;!-- 2. 定义路由的占位符 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<p>在 src/router/index.js 路由模块中，通过 <strong>routes</strong> 数组声明路由的匹配规则</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-comment">// 导入需要使用路由切换展示的组件</span><br><span class="hljs-keyword">import</span> Home <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/Home&#x27;</span><br><span class="hljs-keyword">import</span> Movie <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/Movie&#x27;</span><br><span class="hljs-keyword">import</span> About <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;@/components/About&#x27;</span><br><br><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;<br>  <span class="hljs-attr">routes</span>: [<br>    <span class="hljs-comment">// 在 routes 数组中，声明路由的匹配规则</span><br>    <span class="hljs-comment">// path 表示要匹配的 hash 地址，component 表示要展示的路由组件</span><br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/home&#x27;</span>, <span class="hljs-attr">component</span>: Home &#125;,<br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/movie&#x27;</span>, <span class="hljs-attr">component</span>: Movie &#125;,<br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/about&#x27;</span>, <span class="hljs-attr">component</span>: About &#125;<br>  ]<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<h4 id="路由重定向"><a href="#路由重定向" class="headerlink" title="路由重定向"></a>路由重定向</h4><p>路由重定向指的是：用户在访问地址 A 的时候，强制用户跳转到地址 C ，从而展示特定的组件页面</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;<br>  <span class="hljs-attr">routes</span>: [<br>    <span class="hljs-comment">// 在 routes 数组中，声明路由的匹配规则</span><br>    <span class="hljs-comment">// 重定向的路由规则：当用户访问 / 时，通过 redirect 属性跳转到 &#x27;/home&#x27; 对应的路由规则</span><br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-attr">redirect</span>: <span class="hljs-string">&#x27;/home&#x27;</span> &#125;,<br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/home&#x27;</span>, <span class="hljs-attr">component</span>: Home &#125;<br>    ...<br>  ]<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<h4 id="嵌套路由"><a href="#嵌套路由" class="headerlink" title="嵌套路由"></a>嵌套路由</h4><p>通过路由实现组件的嵌套展示，叫做嵌套路由</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;<br>  <span class="hljs-attr">routes</span>: [<br>    &#123;<br>      <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/about&#x27;</span>,<br>      <span class="hljs-attr">component</span>: About,<br>      <span class="hljs-comment">// 重定向，直接去找 tab1 显示</span><br>      <span class="hljs-attr">redirect</span>: <span class="hljs-string">&#x27;/about/tab1&#x27;</span>,<br>      <span class="hljs-comment">// 通过 children 属性，嵌套声明子级路由规则</span><br>      <span class="hljs-attr">children</span>: [<br>        <span class="hljs-comment">// 子级路由不加 /</span><br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;tab1&#x27;</span>, <span class="hljs-attr">component</span>: Tab1 &#125;,<br>        &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;tab2&#x27;</span>, <span class="hljs-attr">component</span>: Tab2 &#125;<br>      ]<br>    &#125;<br>  ]<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>如果 children 数组中，某个路由的 path 值为空字符串，则这条路由规则叫做 默认路由，进到 根路由 就会默认显示</p>
<p>重定向 和 默认子路由 根据需求随便使用一个均可</p>
</blockquote>
<p>在子组件中配置子路由链接和子路由占位符</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;about-container&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>About 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span><br>    <span class="hljs-comment">&lt;!-- 子级路由链接 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/about/tab1&quot;</span>&gt;</span>tab1<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-link</span> <span class="hljs-attr">to</span>=<span class="hljs-string">&quot;/about/tab2&quot;</span>&gt;</span>tab2<span class="hljs-tag">&lt;/<span class="hljs-name">router-link</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span><br>    <span class="hljs-comment">&lt;!-- 子级路由占位符 --&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">router-view</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">router-view</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<h4 id="动态路由匹配"><a href="#动态路由匹配" class="headerlink" title="动态路由匹配"></a>动态路由匹配</h4><h5 id="概念"><a href="#概念" class="headerlink" title="概念"></a>概念</h5><p>动态路由指的是：把 Hash 地址中可变的部分定义为参数项，从而提高路由规则的复用性。 </p>
<p>在 vue-router 中使用英文的冒号 <code>:</code> 来定义路由的参数项</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">&#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/movie/:id&#x27;</span>, <span class="hljs-attr">component</span>: Movie &#125;<br></code></pre></div></td></tr></table></figure>

<h5 id="route-params-参数对象"><a href="#route-params-参数对象" class="headerlink" title="$route.params 参数对象"></a>$route.params 参数对象</h5><p>在动态路由渲染出来的组件中，可以使用 <strong>this.$route.params</strong> 对象访问到动态匹配的参数值</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;movie-container&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Movie&#123;&#123; $route.params.id &#125;&#125; 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>$route   是路由的 参数对象</p>
<p>$router 是路由的 导航对象</p>
</blockquote>
<h5 id="props-传参"><a href="#props-传参" class="headerlink" title="props 传参"></a>props 传参</h5><p>为了简化路由参数的获取形式，vue-router 允许在路由规则中开启 props 传参</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;<br>  <span class="hljs-attr">routes</span>: [<br>    &#123; <span class="hljs-attr">path</span>: <span class="hljs-string">&#x27;/movie/:id&#x27;</span>, <span class="hljs-attr">component</span>: Movie, <span class="hljs-attr">props</span>: <span class="hljs-literal">true</span> &#125;<br>  ]<br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>在 组件 中通过 props 获取数据</p>
<figure class="highlight html"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs html"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">&quot;movie-container&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Movie&#123;&#123; id &#125;&#125; 组件<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span><br><br><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"></span><br><span class="javascript">  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> &#123;</span><br><span class="javascript">    <span class="hljs-comment">// 接收 props 数据</span></span><br><span class="javascript">    <span class="hljs-attr">props</span>: [<span class="hljs-string">&#x27;id&#x27;</span>]</span><br><span class="javascript">  &#125;</span><br><span class="javascript"></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br></code></pre></div></td></tr></table></figure>

<blockquote>
<p>注意：在 hash 地址中，</p>
<ul>
<li>/ 后面的参数叫做 路径参数，使用 this.$route.params 来访问路径参数</li>
<li>? 后面的参数叫做 查询参数，使用 this.$route.query 来访问</li>
<li>在 this.$route 中，path 只是路径部分，fullPath 是完整的 hash 地址</li>
</ul>
</blockquote>
<h4 id="声明式导航-amp-编程式导航"><a href="#声明式导航-amp-编程式导航" class="headerlink" title="声明式导航 &amp; 编程式导航"></a>声明式导航 &amp; 编程式导航</h4><p>在浏览器中，点击链接实现导航的方式，叫做声明式导航。例如： </p>
<ul>
<li>普通网页中点击 <a> 链接、vue 项目中点击 <router-link> 都属于声明式导航 </router-link></a></li>
</ul>
<p>在浏览器中，调用 API 方法实现导航的方式，叫做编程式导航。例如： </p>
<ul>
<li>普通网页中调用 location.href 跳转到新页面的方式，属于编程式导航</li>
</ul>
<h5 id="vue-中的编程式导航"><a href="#vue-中的编程式导航" class="headerlink" title="vue 中的编程式导航"></a>vue 中的编程式导航</h5><p>vue-router 提供了许多编程式导航的 API，其中最常用的导航 API 分别是： </p>
<ol>
<li><p><code>this.$router.push(&#39;hash 地址&#39;)</code>  </p>
<ul>
<li>跳转到指定的 hash 地址，并<strong>增加</strong>一条历史记录 </li>
</ul>
</li>
<li><p> <code>this.$router.replace(&#39;hash 地址&#39;)</code>  </p>
</li>
</ol>
<ul>
<li>跳转到指定的 hash 地址，并<strong>替换掉</strong>当前的历史记录 </li>
</ul>
<ol start="3">
<li><p><code>this.$router.go(数值 n)</code>  </p>
<ul>
<li>实现导航历史前进、后退</li>
<li>go(-1) 表示后退一层</li>
<li>如果后退的层数超过上限，则原地不动</li>
</ul>
<blockquote>
<p>在实际开发中，一般只会前进一层或后退一层，因此 vue-router 提供了如下两个便捷方法</p>
<ul>
<li>$router.back() ：在历史记录中，后退到上一个页面 </li>
<li>$router.forward() ：在历史记录中，前进到下一个页面</li>
</ul>
</blockquote>
</li>
</ol>
<blockquote>
<p>在行内使用 编程式跳转 时，this 必须要省略，否则会报错</p>
</blockquote>
<h4 id="导航守卫"><a href="#导航守卫" class="headerlink" title="导航守卫"></a>导航守卫</h4><p>导航守卫可以控制路由的访问权限</p>
<h5 id="全局前置守卫"><a href="#全局前置守卫" class="headerlink" title="全局前置守卫"></a>全局前置守卫</h5><p>调用路由实例对象的 <strong>beforeEach()</strong> 方法，即可声明全局前置守卫</p>
<p>在 main.js 中配置：</p>
<p>全局前置守卫的回调函数中接收 3 个形参</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-keyword">const</span> router = <span class="hljs-keyword">new</span> VueRouter(&#123;&#125;)<br><br><span class="hljs-comment">// 每次发生路由的导航跳转时，都会自动触发 fn 这个 “回调函数”</span><br>router.beforeEach(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span>, next</span>) =&gt;</span> &#123;<br>  <span class="hljs-comment">// to 表示将要访问的路由信息对象</span><br>  <span class="hljs-comment">// from 表示将要离开的路由信息对象</span><br>  <span class="hljs-comment">// next 是一个方法，表示放行，允许这次路由导航</span><br>&#125;)<br></code></pre></div></td></tr></table></figure>

<p>next 函数的三种调用方式</p>
<ul>
<li>当前用户<strong>拥有</strong>后台主页的访问权限，直接<strong>放行</strong>：==next()== </li>
<li>当前用户<strong>没有</strong>后台主页的访问权限，强制其<strong>跳转到登录页面</strong>：==next(‘/login’)== </li>
<li>当前用户<strong>没有</strong>后台主页的访问权限，<strong>不允许跳转</strong>到后台主页：==next(false)== </li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js">router.beforeEach(<span class="hljs-function">(<span class="hljs-params">to, <span class="hljs-keyword">from</span>, next</span>) =&gt;</span> &#123;<br>  <span class="hljs-keyword">if</span> (to.path === <span class="hljs-string">&#x27;/main&#x27;</span>) &#123;<br>    <span class="hljs-comment">// 获取 token 值</span><br>    <span class="hljs-keyword">const</span> token = <span class="hljs-built_in">localStorage</span>.getItem(<span class="hljs-string">&#x27;token&#x27;</span>)<br>    <span class="hljs-keyword">if</span> (token) next() <span class="hljs-comment">// 已登录，放行</span><br>    <span class="hljs-keyword">else</span> next(<span class="hljs-string">&#x27;/login&#x27;</span>) <span class="hljs-comment">// 未登录，跳转到指定页面，一般为登录页</span><br>  &#125; <span class="hljs-keyword">else</span> next()<br>&#125;)<br></code></pre></div></td></tr></table></figure>



<h1 id="Eslint"><a href="#Eslint" class="headerlink" title="Eslint"></a>Eslint</h1><p>一个插件化的javascript代码检测工具</p>
<h2 id="基本使用-1"><a href="#基本使用-1" class="headerlink" title="基本使用"></a>基本使用</h2><p>生成 .eslintrc.js 文件</p>
<figure class="highlight js"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs js"><span class="hljs-built_in">module</span>.exports = &#123;<br>  <span class="hljs-attr">root</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">env</span>: &#123;<br>    <span class="hljs-attr">node</span>: <span class="hljs-literal">true</span><br>  &#125;,<br>  <span class="hljs-attr">extends</span>: [<br>    <span class="hljs-string">&#x27;plugin:vue/essential&#x27;</span>,<br>    <span class="hljs-string">&#x27;@vue/standard&#x27;</span><br>  ],<br>  <span class="hljs-attr">parserOptions</span>: &#123;<br>    <span class="hljs-attr">parser</span>: <span class="hljs-string">&#x27;babel-eslint&#x27;</span><br>  &#125;,<br>  <span class="hljs-attr">rules</span>: &#123;<br>    <span class="hljs-string">&#x27;no-console&#x27;</span>: process.env.NODE_ENV === <span class="hljs-string">&#x27;production&#x27;</span> ? <span class="hljs-string">&#x27;warn&#x27;</span> : <span class="hljs-string">&#x27;off&#x27;</span>,<br>    <span class="hljs-string">&#x27;no-debugger&#x27;</span>: process.env.NODE_ENV === <span class="hljs-string">&#x27;production&#x27;</span> ? <span class="hljs-string">&#x27;warn&#x27;</span> : <span class="hljs-string">&#x27;off&#x27;</span><br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<ul>
<li>process.env.NODE_ENV 固定用法，获取到 webpack 的模式</li>
<li>在 rules 中写规则</li>
<li>no-console 禁用输出指令</li>
<li>no-debugger 禁用断点代码</li>
</ul>
<blockquote>
<p>想要自定义规则可以去官网上寻找</p>
</blockquote>
<h2 id="VScode-配置"><a href="#VScode-配置" class="headerlink" title="VScode 配置"></a>VScode 配置</h2><h3 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h3><h4 id="ESlint-Dirk-Baeumer"><a href="#ESlint-Dirk-Baeumer" class="headerlink" title="ESlint (Dirk Baeumer)"></a>ESlint (Dirk Baeumer)</h4><p>在 settings.json 配置：</p>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123;<br>  <span class="hljs-comment">// ESLint 插件的配置</span><br>  <span class="hljs-attr">&quot;editor.codeActionsOnSave&quot;</span>: &#123;<br>    <span class="hljs-attr">&quot;source.fixAll&quot;</span>: <span class="hljs-literal">true</span><br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<h4 id="Prettier-Code-formatter-Prettier"><a href="#Prettier-Code-formatter-Prettier" class="headerlink" title="Prettier - Code formatter (Prettier)"></a>Prettier - Code formatter (Prettier)</h4><p>在 settings.json 中配置：</p>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123;<br>  <span class="hljs-attr">&quot;prettier.configPath&quot;</span>: <span class="hljs-string">&quot;C:\\Users\\AgoniLay\\.prettierrc&quot;</span>,<br><br>  <span class="hljs-attr">&quot;eslint.alwaysShowStatus&quot;</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">&quot;prettier.trailingComma&quot;</span>: <span class="hljs-string">&quot;none&quot;</span>,<br>  <span class="hljs-attr">&quot;prettier.semi&quot;</span>: <span class="hljs-literal">false</span>,<br>  <span class="hljs-comment">// 每行文字个数超出限制将会被迫换行</span><br>  <span class="hljs-attr">&quot;prettier.printWidth&quot;</span>: <span class="hljs-number">300</span>,<br>  <span class="hljs-comment">// 使用单引号替换双引号</span><br>  <span class="hljs-attr">&quot;prettier.singleQuote&quot;</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">&quot;prettier.arrowParens&quot;</span>: <span class="hljs-string">&quot;avoid&quot;</span>,<br>  <span class="hljs-comment">// 设置 .vue 文件中，HTML代码的格式化插件</span><br>  <span class="hljs-attr">&quot;vetur.format.defaultFormatter.html&quot;</span>: <span class="hljs-string">&quot;js-beautify-html&quot;</span>,<br>  <span class="hljs-comment">// 忽略项目中的警告弹窗</span><br>  <span class="hljs-attr">&quot;vetur.ignoreProjectWarning&quot;</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">&quot;vetur.format.defaultFormatterOptions&quot;</span>: &#123;<br>    <span class="hljs-attr">&quot;prettier&quot;</span>: &#123;<br>      <span class="hljs-attr">&quot;trailingComma&quot;</span>: <span class="hljs-string">&quot;none&quot;</span>,<br>      <span class="hljs-attr">&quot;semi&quot;</span>: <span class="hljs-literal">false</span>,<br>      <span class="hljs-attr">&quot;singleQuote&quot;</span>: <span class="hljs-literal">true</span>,<br>      <span class="hljs-attr">&quot;arrowParens&quot;</span>: <span class="hljs-string">&quot;aviod&quot;</span>,<br>      <span class="hljs-attr">&quot;printWidth&quot;</span>: <span class="hljs-number">300</span><br>    &#125;,<br>    <span class="hljs-attr">&quot;js-beautify-html&quot;</span>: &#123;<br>      <span class="hljs-attr">&quot;wrap_attribute&quot;</span>: <span class="hljs-literal">false</span><br>    &#125;<br>  &#125;<br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>其中也包含 vetur 插件的配置设置</p>
<p>在本地 C盘/用户/xxx 目录下 创建 .pretterrc 文件</p>
<p>在其中设置：</p>
<figure class="highlight json"><table><tr><td class="gutter hljs"><div class="hljs code-wrapper"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></div></td><td class="code"><div class="hljs code-wrapper"><pre><code class="hljs json">&#123;<br>  <span class="hljs-attr">&quot;semi&quot;</span>: <span class="hljs-literal">false</span>,<br>  <span class="hljs-attr">&quot;singleQuote&quot;</span>: <span class="hljs-literal">true</span>,<br>  <span class="hljs-attr">&quot;printWidth&quot;</span>: <span class="hljs-number">300</span>,<br>  <span class="hljs-attr">&quot;arrowParens&quot;</span>: <span class="hljs-string">&quot;avoid&quot;</span>,<br>  <span class="hljs-attr">&quot;trailingComma&quot;</span>: <span class="hljs-string">&quot;none&quot;</span><br>&#125;<br></code></pre></div></td></tr></table></figure>

<p>在项目中设置 .vue 和 .js 结尾的文件 格式化文档方式默认为  Pretter - Code - formatter</p>
<ul>
<li>右键选择 使用…格式化文档</li>
</ul>

            </div>
            <hr>
            <div>
              <div class="post-metas mb-3">
                
                  <div class="post-meta mr-3">
                    <i class="iconfont icon-category"></i>
                    
                      <a class="hover-with-bg" href="/categories/%E5%89%8D%E7%AB%AF/">前端</a>
                    
                  </div>
                
                
                  <div class="post-meta">
                    <i class="iconfont icon-tags"></i>
                    
                      <a class="hover-with-bg" href="/tags/vue/">vue</a>
                    
                      <a class="hover-with-bg" href="/tags/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/">前端框架</a>
                    
                      <a class="hover-with-bg" href="/tags/vue2/">vue2</a>
                    
                  </div>
                
              </div>
              
                <p class="note note-warning">
                  
                    本博客所有文章除特别声明外，均为本人原创，转载请注明出处！
                  
                </p>
              
              
                <div class="post-prevnext">
                  <article class="post-prev col-6">
                    
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/08/04/CSS%E7%AC%94%E8%AE%B0/">
                        <span class="hidden-mobile">CSS笔记</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>
    
      <div class="d-none d-lg-block col-lg-2 toc-container" id="toc-ctn">
        <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>

      </div>
    
  </div>
</div>

<!-- Custom -->

  <div class="col-lg-7 mx-auto nopadding-x-md">
    <div class="container custom post-custom mx-auto">
      <img src="/img/agoni.gif" srcset="/img/loading2.gif" lazyload class="rounded mx-auto d-block mt-5" style="width:150px; height:150px;"> <h5 style="text-align: center; margin-top: 1rem;">谢谢您的光临噢！！！</h5> 
    </div>
  </div>


    

    
      <a id="scroll-top-button" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v"
                 for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>
    

    
  </main>

  <footer class="text-center mt-5 py-3">
  <div class="footer-content">
     <span>张宝文</span> <i class="iconfont icon-love"></i> <span>郑佳丽</span>  
	<!--《添加网站运行时间 -->
<br/>

<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
var now = new Date(); 

function createtime() {
    //此处修改你的建站时间或者网站上线时间
    var grt = new Date('07/28/2021 19:00:00');
    now.setTime(now.getTime() + 250);
    days = (now - grt) / 1000 / 60 / 60 / 24;

    dnum = Math.floor(days);
    hours = (now - grt) / 1000 / 60 / 60 - (24 * dnum);
    hnum = Math.floor(hours);
    if (String(hnum).length == 1) {
        hnum = "0" + hnum;
    }
    minutes = (now - grt) / 1000 / 60 - (24 * 60 * dnum) - (60 * hnum);
    mnum = Math.floor(minutes);
    if (String(mnum).length == 1) {
        mnum = "0" + mnum;
    }
    seconds = (now - grt) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
    snum = Math.round(seconds);
    if (String(snum).length == 1) {
        snum = "0" + snum;
    }
    document.getElementById("timeDate").innerHTML = " 本站已各种夹缝中安全运行 " + dnum + " 天 ";
    document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + " 分 " + snum + " 秒";
}
setInterval("createtime()", 250);
</script>

<!-- 添加网站运行时间》-->
  </div>
  
  <div class="statistics">
    
    

    
      
        <!-- 不蒜子统计PV -->
        <span id="busuanzi_container_site_pv" style="display: none">
            总访问量 
            <span id="busuanzi_value_site_pv"></span>
             次
          </span>
      
      
        <!-- 不蒜子统计UV -->
        <span id="busuanzi_container_site_uv" style="display: none">
            总访客数 
            <span id="busuanzi_value_site_uv"></span>
             人
          </span>
      
    
  </div>


  

  
</footer>


  <!-- SCRIPTS -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>

<!-- Plugins -->


  
    <script  src="/js/img-lazyload.js" ></script>
  



  



  <script  src="https://cdn.jsdelivr.net/npm/tocbot@4.12.3/dist/tocbot.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js" ></script>



  <script  src="https://cdn.jsdelivr.net/npm/anchor-js@4.3.1/anchor.min.js" ></script>



  <script defer src="https://cdn.jsdelivr.net/npm/clipboard@2.0.8/dist/clipboard.min.js" ></script>



  <script  src="/js/local-search.js" ></script>



  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>




  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2.0.12/lib/typed.min.js" ></script>
  <script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>

  <script>
    function typing(id, title){
        var typed = new Typed('#' + id, {
            strings: [
              '  ',
              title + "&nbsp;",
            ],
            cursorChar: "❤",
            typeSpeed: 150,
            loop: false,
        });
        typed.stop();
        $(document).ready(function () {
            $(".typed-cursor").addClass("h2");
            typed.start();
        });
    }

    
        typing("subtitle", document.getElementById('subtitle').title)
    

  </script>













  
<script src="//cdn.jsdelivr.net/gh/bynotes/texiao/source/js/yinghua.js"></script>



<!-- 主题的启动项 保持在最底部 -->
<script  src="/js/boot.js" ></script>

</body>
</html>
